为了账号安全,请及时绑定邮箱和手机立即绑定

Swift中performSelector的替代选择?

Swift中performSelector的替代选择?

江户川乱折腾 2019-10-11 10:46:39
该performSelector方法的家庭中未提供斯威夫特。那么,如何在@objc对象上调用方法,而要在运行时选择要调用的方法,而在编译时却不知道该方法呢?NSInvocation显然在Swift中也不可用。我知道在Swift中,您可以将任何方法(对于该@objc方法可见的方法声明)发送给type AnyObject,类似于id在Objective-C中。但是,这仍然需要您在编译时对方法名称进行硬编码。有没有办法在运行时动态选择它?
查看完整描述

3 回答

?
子衿沉夜

TA贡献1828条经验 获得超3个赞

使用闭包


class A {

    var selectorClosure: (() -> Void)?


    func invoke() {

        self.selectorClosure?()

    }

}


var a = A()

a.selectorClosure = { println("Selector called") }

a.invoke()

请注意,这并不是什么新鲜事物,即使在Obj-C中,新的API也更喜欢使用块performSelector(与new 相比UIAlertView,比较使用respondsToSelector:和performSelector:调用委托方法UIAlertController)。


使用performSelector:始终是不安全的,并且不能与ARC配合使用(因此有ARC警告performSelector:)。


查看完整回答
反对 回复 2019-10-11
?
慕虎7371278

TA贡献1802条经验 获得超4个赞

方法A

使用NSThread.detachNewThreadSelector,关于这种方法的好处是我们可以将对象附加到消息上。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)")

}

控制台日志:


问候世界


附加对象:阳光


方法B

这个替代方法是较早发现的,我也在设备和模拟器上进行了测试。这个想法是使用UIControl的以下方法:


func sendAction(_ action: Selector, to target: AnyObject!, forEvent event: UIEvent!)

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")

}

控制台日志:


问候世界


方法C

NSTimer


class func scheduledTimerWithTimeInterval(_ seconds: NSTimeInterval,

                                      target target: AnyObject!,

                                 selector aSelector: Selector,

                                  userInfo userInfo: AnyObject!,

                                    repeats repeats: Bool) -> NSTimer!


查看完整回答
反对 回复 2019-10-11
?
尚方宝剑之说

TA贡献1788条经验 获得超4个赞

按照@JTerry的回答“在Swift中不需要选择器”,您可以将实际方法分配给变量。我的解决方案如下(我在方法中需要一个参数):


class SettingsMenuItem: NSObject {

    ...

    var tapFunction: ((sender: AnyObject?) -> ())?

}

然后在视图控制器中,我以这种方式声明,分配和运行该函数:


class SettingsViewController: UITableViewController {


    func editProfile(sender: AnyObject?) {

        ...

    }


    ...


    menuItem.tapFunction = editProfile


    ...


    if let tapFunction = menuItem.tapFunction {

        tapFunction(sender: self)

    }



}


查看完整回答
反对 回复 2019-10-11
  • 3 回答
  • 0 关注
  • 886 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信