pprevalon pprevalon - 2 months ago 10
Swift Question

Swift how to create action inside of a method

Is it possible to create an action inside of a method.

func hello(){
button.addtarget(self.,#selector(itemTocall),forControlEvents:TouchInside)

let itemTocall = {
print("hello")
}

}

Answer

Not in quite the way you mean, but broadly speaking, yes. First, remember that target/action was developed many, many years before closures. So there's really no overlap in the functionality. The action must be a specific selector, which must exist statically. But, we can do whatever we want at that point. For example, we could build this simply like:

class Something: NSObject {

    let button = UIButton()

    var dispatchFunc: (UIButton) -> Void = {_ in}

    func dispatch(button: UIButton) {
        dispatchFunc(button)
    }

    func hello(){
        dispatchFunc = {_ in
            print("hello")
        }

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

Now, dispatchFunc is rewritten to be whatever you want the behavior to be, and dispatch just exists as a middleman. This technique can of course be extended significantly. You could have a dictionary of buttons (or button IDs) to closures so that lots of different buttons could dynamically change what they ran (even though they all point to the same dispatch function). Or you could have an array of closures so that multiple actions could be performed. Whatever you want.

(There are many other ways to achieve this, such as using the ObjC runtime. You could override message dispatching and handle arbitrary selectors that don't even have backing methods, but I'd recommend something simple like the above with closures.)