Swift51.com
J_K_D 头像
J_K_D  2017-10-05 15:53

关于用柯里化实现Target-Action的疑问

回复:0  查看:4114  
在看了喵神的书籍后,一直有个疑问,就是里面说到的使用swift的柯里化来封装Target-Action模式。先上代码( 代码中稍微有改动,我将Control继承了UIButton):

protocol TargetAction {

    func performAction()

}



struct TargetActionWrapper<T: AnyObject> : TargetAction {

    weak var target: T?

    let action: (T) -> () -> ()

    

    func performAction() -> () {

        if let t = target {

            action(t)()

        }

    }

}



enum ControlEvent {

    case TouchUpInside

    case ValueChanged

    // ...

}



class Control : UIButton{

    var actions = [ControlEvent: TargetAction]()

    

    func setTarget<T: AnyObject>(target: T, action: @escaping (T) -> () -> (), controlEvent: ControlEvent) {

        actions[controlEvent] = TargetActionWrapper(target: target, action: action)

    }

    

    func removeTargetForControlEvent(controlEvent: ControlEvent) {

        actions[controlEvent] = nil

    }

    

    func performActionForControlEvent(controlEvent: ControlEvent) {

        actions[controlEvent]?.performAction()

    }

}


然后查了原本出自的博客文,说是这样使用 
class MyViewController {

    let button = Control()

    

    func viewDidLoad() {

        button.setTarget(target: self, action: MyViewController.onButtonTap, controlEvent: .TouchUpInside)

    }

    

    func onButtonTap() {

        print("Button was tapped")

    }

}

  然后我就发现,onButtonTap这个方法是没办法触发的,除非,我自己给button添加一个target-action,然后在自己绑定的Action里 面条用performActionForControlEvent方法。代码如下:
class ViewController: UIViewController {

    let button = Control.init(frame: CGRect.init(x: 0, y: 0, width: 100, height: 40))

    override func viewDidLoad() {

        super.viewDidLoad()

        button.center = self.view.center

        button.setTitle("anniu", for: .normal)

        button.backgroundColor = UIColor.blue

        self.view.addSubview(button)

        // Do any additional setup after loading the view, typically from a nib.

        button.setTarget(target: self, action: ViewController.onButtonTap, controlEvent: .TouchUpInside)

        

        button.addTarget(self, action: #selector(ViewController.action), for: .touchUpInside)

    }

    @objc func action(){

        button.performActionForControlEvent(controlEvent: .TouchUpInside)

    }

    func onButtonTap() {

        print("Button click")

    }

    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }





}

如果要这样使用,封装的意义在哪里,不是画蛇添足吗?求大神解答,谢谢。