【问题标题】:How to correctly pass selector as parameter in swift如何在swift中正确传递选择器作为参数
【发布时间】:2015-07-08 22:40:40
【问题描述】:

总之

我有一个包含 B 实例的 A 类。在 A 类中,我将 A 的一个函数作为选择器传递给 B 的 A 方法。B 使用这个选择器来注册通知。但是,当通知进来时,它无法运行选择器并显示“无法识别的选择器已发送到实例”。如果我把我想在 B 班做的所有事情都转移到 A 班,它就奏效了。但是,我希望它们分开,以便看起来更有条理。我对 Objective-C 和 Swift 相当陌生,因此,在这种情况下,我不知道如何将选择器作为参数传递。用 Swift 回答会很棒。

ViewController.swift

class ViewController: UIViewController {

    var sessionCtrl : GKSessionControllerH!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        sessionCtrl = GKSessionControllerH()

        //  register notifications
        registerNotification()
    }

    func registerNotification() {
        sessionCtrl.registerNotification(GKGesture.Up, gestureHandler: "gestureUpHandler")
    }

    func gestureUpHandler() {
        dispatch_async(dispatch_get_main_queue()) {
            self.slidesViewCtrl!.prevPage()
        }
    }
}

GKSessionControllerH.swift

class GKSessionControllerH: NSObject, WCSessionDelegate {

    func handleGestureContent(content : AnyObject?) {

        // retrieve gesture
        let gesture = GKGesture(rawValue: content as! String)!
        print("Handheld device receives \(gesture)")

        //  post notification
        let notificationName = "ReceiveGesture\(gesture.rawValue)"
        NSNotificationCenter.defaultCenter().postNotificationName(notificationName, object: nil)

    }

    func registerNotification(gesture : GKGesture, gestureHandler : Selector) {

        let notificationName = "ReceiveGesture\(gesture.rawValue)"
        NSNotificationCenter.defaultCenter().addObserver(self, selector: gestureHandler, name: notificationName, object: nil)

    }
}

调试信息

2015-07-08 17:26:26.534 Slider[4608:1719498] -[Slider.GKSessionControllerH gestureDownHandler]: unrecognized selector sent to instance 0x7f912857a420
2015-07-08 17:26:26.543 Slider[4608:1719498] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Slider.GKSessionControllerH gestureDownHandler]: unrecognized selector sent to instance 0x7f912857a420'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010430dca5 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x00000001060f1dcd objc_exception_throw + 48
    2   CoreFoundation                      0x0000000104315fcd -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
    3   CoreFoundation                      0x00000001042634ea ___forwarding___ + 970
    4   CoreFoundation                      0x0000000104263098 _CF_forwarding_prep_0 + 120
    5   CoreFoundation                      0x00000001042db09c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    6   CoreFoundation                      0x00000001042daddb _CFXRegistrationPost + 427
    7   CoreFoundation                      0x00000001042dab42 ___CFXNotificationPost_block_invoke + 50
    8   CoreFoundation                      0x000000010431d432 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1618
    9   CoreFoundation                      0x00000001041d3538 _CFXNotificationPost + 632
    10  Foundation                          0x00000001048bb3c4 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
    11  Slider                              0x00000001040f4e0e _TFC6Slider20GKSessionControllerH20handleGestureContentfS0_FGSqPSs9AnyObject__T_ + 1086
    12  Slider                              0x00000001040f4689 _TFC6Slider20GKSessionControllerH7sessionfS0_FTCSo9WCSession17didReceiveMessageGVSs10DictionarySSPSs9AnyObject___T_ + 825
    13  Slider                              0x00000001040f49b7 _TToFC6Slider20GKSessionControllerH7sessionfS0_FTCSo9WCSession17didReceiveMessageGVSs10DictionarySSPSs9AnyObject___T_ + 119
    14  WatchConnectivity                   0x00000001060c18cd WatchConnectivity + 35021
    15  libdispatch.dylib                   0x0000000106ab2b11 _dispatch_call_block_and_release + 12
    16  libdispatch.dylib                   0x0000000106ad280d _dispatch_client_callout + 8
    17  libdispatch.dylib                   0x0000000106ab92ec _dispatch_queue_drain + 2200
    18  libdispatch.dylib                   0x0000000106ab88ed _dispatch_queue_invoke + 233
    19  libdispatch.dylib                   0x0000000106abae9b _dispatch_root_queue_drain + 1412
    20  libdispatch.dylib                   0x0000000106aba912 _dispatch_worker_thread3 + 111
    21  libsystem_pthread.dylib             0x0000000106e11637 _pthread_wqthread + 729
    22  libsystem_pthread.dylib             0x0000000106e0f40d start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException

【问题讨论】:

    标签: ios swift selector


    【解决方案1】:

    这是控制台输出中的重要线索:

    -[Slider.GKSessionControllerH gestureDownHandler]:无法识别的选择器发送到实例 0x7f912857a420

    所以,问题在于,GKSessionControllerH 将自己注册为通知的接收者,而不是尝试在您的 ViewController 上调用 gestureDownHandler

    我们需要同时传入选择器对象来调用选择器。

    func registerNotification(gesture: GKGesture, gestureHandler: AnyObject, selector: Selector) {
        let notificationName = "ReceiveGesture\(gesture.rawValue)"
        NSNotificationCenter.defaultCenter().addObserver(gestureHandler, selector: gestureHandler, name: notificationName, object: nil)
    }
    

    现在,注册:

    sessionCtrl.registerNotification(.Up, gestureHandler: self, selector: "gestureUpHandler")
    

    或者,可以说更像 Swift,我们可以采用更基于闭包的方法。

    首先,让GKSessionControllerH 接收通知,然后我们将传递给它一个闭包,它会在收到通知时跟踪调用。

    GKSessionControllerH

    var gestureActions = [()->Void] // an array of void-void closures
    
    func gestureHandler() {
        for action in gestureActions {
            action()
        }
    }
    
    func registerNotification(gesture: GKGesture, action:()->Void) {
        let notificationName = "ReceiveGesture\(gesture.rawValue)"
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "gestureHandler", name: notificationName, object: nil)
    }
    

    现在,我们传入一个闭包(可以是一个方法):

    ViewController:

    func registerNotification() {
        sessionCtrl.registerNotification(.Up, action: gestureUpHandler)
    }
    

    现在显然,这需要更多的逻辑来处理所有不同的手势类型,但要点在这里。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-25
      • 2021-02-22
      • 1970-01-01
      相关资源
      最近更新 更多