Alternative to performSelector in Swift?
Solution 1:
Using closures
class A {
var selectorClosure: (() -> Void)?
func invoke() {
self.selectorClosure?()
}
}
var a = A()
a.selectorClosure = { println("Selector called") }
a.invoke()
Note that this is nothing new, even in Obj-C the new APIs prefer using blocks over performSelector
(compare UIAlertView
which uses respondsToSelector:
and performSelector:
to call delegate methods, with the new UIAlertController
).
Using performSelector:
is always unsafe and doesn't play well with ARC (hence the ARC warnings for performSelector:
).
Solution 2:
As of Xcode 7, the full family of performSelector methods are available in Swift, including performSelectorOnMainThread()
and performSelectorInBackground()
. Enjoy!
Solution 3:
Approach A
Use NSThread.detachNewThreadSelector
, good thing about this approach is that we can attach object to the message. Example code in ViewController:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let delay = 2.0 * Double(NSEC_PER_SEC)
var time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue(), {
NSThread.detachNewThreadSelector(Selector("greetings:"), toTarget:self, withObject: "sunshine")
})
}
func greetings(object: AnyObject?) {
println("greetings world")
println("attached object: \(object)")
}
Console log:
greetings world
attached object: sunshine
Approach B
This alternative was discovered earlier, I have also tested on device and simulator. The idea is to use following method of UIControl:
func sendAction(_ action: Selector, to target: AnyObject!, forEvent event: UIEvent!)
Example code in ViewController:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var control: UIControl = UIControl()
control.sendAction(Selector("greetings"), to: self, forEvent: nil) // Use dispatch_after to invoke this line as block if delay is intended
}
func greetings() {
println("greetings world")
}
Console log:
greetings world
Approach C
NSTimer
class func scheduledTimerWithTimeInterval(_ seconds: NSTimeInterval,
target target: AnyObject!,
selector aSelector: Selector,
userInfo userInfo: AnyObject!,
repeats repeats: Bool) -> NSTimer!