最后说
我有一个包含B的实例的A类.在A类中,我将一个A作为选择器的函数传递给B的一个方法.B使用这个选择器注册通知.但是,当通知进入时,它无法运行选择器并显示“无法识别的选择器发送到实例”.如果我把所有我想在B班做的事情都移到A班,那就行了.不过,我希望他们分开,好像更有条理.我对Objective-C和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
解决方法
以下是您的控制台输出中的大线索:
-[Slider.GKSessionControllerH gestureDownHandler]: unrecognized selector sent to instance 0x7f912857a420
所以,问题是,而不是试图在您的ViewController上调用gestureDownHandler,GKSessionControllerH正在注册为通知的接收者.
我们需要传递选择器和对象来调用选择器.
- func registerNotification(gesture: GKGesture,gestureHandler: AnyObject,selector: Selector) {
- let notificationName = "ReceiveGesture\(gesture.rawValue)"
- NSNotificationCenter.defaultCenter().addObserver(gestureHandler,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",object: nil)
- }
现在,我们通过一个闭包(可以是一个方法):
在ViewController中:
- func registerNotification() {
- sessionCtrl.registerNotification(.Up,action: gestureUpHandler)
- }
现在显然,这将需要更多的逻辑来处理所有不同的手势类型,但它的要点在这里.