Swift Target-Action、Curring 设计模式

自定义实现类似UIButtonaddTarget事件响应链

沿用OC调用方式

动态调用

声明

    weak var target: AnyObject?;
    var action: Selector?;
    func addTarget(_ target: AnyObject, selector: Selector) {
        self.target = target;
        self.action = selector;
    }

调用

    if let target = target, let selector = action {
        if let method = class_getInstanceMethod(type(of: target), selector) {
            let imp = method_getImplementation(method);
            typealias Function = @convention(c) (AnyObject, Selector, Any?) -> ();
            let function = unsafeBitCast(imp, to: Function.self);
            function(target, selector, self);
        }
    }
Swift Curring柯里化方式

声明

protocol TargetAction {
    func performAction();
}

struct TargetActionWrapper: TargetAction {
    weak var target: T?;
    let action: (T) -> () -> ();
    
    func performAction() {
        if let t = target {
            action(t)();
        }
    }
}

class Model: NSObject {
    var wrapper: TargetAction?
    func addTarget(target: T, action: @escaping (T) -> () -> ()) {
         wrapper = TargetActionWrapper(target: target, action: action);
    }
    
    func invoke() {
        wrapper?.performAction();
    }
}

调用

let model = Model();
model.addTarget(target: self, action: Test.invokeAction);

func invokeAction() {}

上面方法无法传递参数,需要进一步扩展。扩展可以根据自己需要,此处只简单举例。

protocol TargetAction {
    func performAction(_ userInfo: Any?);
}

struct TargetActionWrapper: TargetAction {
    weak var target: T?;
    let action: (T) -> (Any?) -> ();
    
    func performAction(_ userInfo: Any?) {
        if let t = target {
            action(t)(userInfo);
        }
    }
}

class Model: NSObject {
    var wrapper: TargetAction?
    var userInfo: Any?;
    func addTarget(target: T, action: @escaping (T) -> (Any?) -> (), userInfo: Any? = nil) {
        self.userInfo = userInfo;
         wrapper = TargetActionWrapper(target: target, action: action);
    }
    
    func invoke() {
        wrapper?.performAction(userInfo);
    }
}

// 调用
let model = Model();
model.addTarget(target: self, action: Test.invokeAction, userInfo: ["a": "b"]);

func invokeAction(_ sender: Any) {}

你可能感兴趣的:(Swift Target-Action、Curring 设计模式)