2015-07-08 3 views
14

SchlüssigWie Sie sich richtig Selektor als Parameter in schnellen

sprechen passieren

I Klasse A haben, die eine Instanzen B. enthält und in der Klasse A, gebe ich eine Funktion von A als Wähler auf ein Verfahren von B. und B Verwenden Sie diesen Selektor, um die Benachrichtigung zu registrieren. Wenn die Benachrichtigung jedoch eingeht, konnte sie den Selektor nicht ausführen und "unerkannter Selektor, der an Instanz gesendet wird" anzeigen. Wenn ich alles, was ich in der Klasse B machen will, in die Klasse A bringe, hat es funktioniert. Ich möchte jedoch, dass sie getrennt sind, so dass es organisierter erscheint. Ich bin ziemlich neu in Objective-C und Swift, daher weiß ich nicht, wie man in diesem Fall den Selektor als Parameter übergibt. Antwort in Swift wäre großartig.

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) 

    } 
} 

Debug-Informationen

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 

Antwort

12

Her e ist die große Ahnung, in der Konsole ausgegeben:

- [Slider.GKSessionControllerH gestureDownHandler]: Unbekannter Selektor 0x7f912857a420

So zum Beispiel gesendet wird, ist das Problem, dass anstatt zu versuchen, gestureDownHandler auf ViewController anrufen registriert sich selbst als Empfänger der Benachrichtigung.

Wir müssen sowohl den Selektor als auch das Objekt übergeben, um den Selektor anzurufen.

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

Und jetzt registrieren:

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

Alternativ und wohl mehr Swift-like, wir eine Schließung basierten Ansatz nehmen.

Lassen Sie uns zuerst die Benachrichtigungen erhalten, und wir werden es eine Schließung übergeben, die es nachverfolgen wird, um anzurufen, wenn die Benachrichtigung empfangen wird.

In 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) 
} 

Und jetzt gehen wir in einem Verschluss (die ein Verfahren sein kann):

In ViewController:

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

Jetzt offensichtlich, diese müssen ein wenig mehr Logik, um alle Ihre verschiedenen Gesten zu behandeln, aber das Wesentliche davon ist hier.