在 swift 中添加通知观察者

Adding a notification observer in swift

还有其他与此相关的 Whosebug 问题,但我提到的解决方案似乎不适用于此问题。我有一个 NSTextField,每次字段中的文本更改时我都希望得到通知。我有一个 NSViewController 控制包含 NSTextField 的视图,它将成为观察者。

我的 class 看起来像这样:

import Cocoa

class ADDViewController: NSViewController
{
    @IBOutlet weak var fieldText:   NSTextField!



    func fieldTextChanged( notification: NSNotification )
    {
        println( "fieldTextChanged" )
    }



    override var nibName: String?
    {
        return "ADDViewController"
    }



    override func viewDidLoad()
    {
        super.viewDidLoad()

        NSNotificationCenter.defaultCenter().addObserver( self, selector: "fieldTextChanged:" as Selector, name: NSControlTextDidChangeNotification, object: fieldText )
    }
}

正在添加并触发通知。当我在字段中键入一个字符时,我在堆栈跟踪中看到:

#0  0x00007fff905880e9 in objc_msgSend ()
#1  0x00007fff8f27c45c in __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ ()
#2  0x00007fff8f16c634 in _CFXNotificationPost ()
#3  0x00007fff8fcf0aa1 in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#4  0x00007fff8f27c45c in __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ ()
#5  0x00007fff8f16c634 in _CFXNotificationPost ()
#6  0x00007fff8fcf0aa1 in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#7  0x00007fff8ab3deb1 in -[NSTextView(NSSharing) didChangeText] ()

就在它崩溃之前。我确实尝试将选择器更改为:

@objc func fieldTextChanged( notification: NSNotification )
{
    println( "fieldTextChanged" )
}

但是,当我这样做时,它仍然不起作用。我在控制台中看到的内容:

2015-08-23 18:36:32.240 addobserver_test[52788:3477511] -[__NSCFString fieldTextChanged:]: unrecognized selector sent to instance 0x6000000c3720
2015-08-23 18:36:32.240 addobserver_test[52788:3477511] An uncaught exception was raised
2015-08-23 18:36:32.240 addobserver_test[52788:3477511] -[__NSCFString fieldTextChanged:]: unrecognized selector sent to instance 0x6000000c3720
2015-08-23 18:36:32.244 addobserver_test[52788:3477511] (
    0   CoreFoundation                      0x00007fff8f2c003c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff9059576e objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff8f2c30ad -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
    3   CoreFoundation                      0x00007fff8f208e24 ___forwarding___ + 1028
    4   CoreFoundation                      0x00007fff8f208998 _CF_forwarding_prep_0 + 120
    5   CoreFoundation                      0x00007fff8f27c45c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    6   CoreFoundation                      0x00007fff8f16c634 _CFXNotificationPost + 3140
    7   Foundation                          0x00007fff8fcf0aa1 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
    8   CoreFoundation                      0x00007fff8f27c45c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    9   CoreFoundation                      0x00007fff8f16c634 _CFXNotificationPost + 3140
    10  Foundation                          0x00007fff8fcf0aa1 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
    11  AppKit                              0x00007fff8ab3deb1 -[NSTextView(NSSharing) didChangeText] + 348
    12  AppKit                              0x00007fff8ab3b13b -[NSTextView insertText:replacementRange:] + 2827
    13  AppKit                              0x00007fff8ab3a237 -[NSTextInputContext(NSInputContext_WithCompletion) insertText:replacementRange:completionHandler:] + 98
    14  AppKit                              0x00007fff8ab3a1ca __55-[NSTextInputContext handleTSMEvent:completionHandler:]_block_invoke_2242 + 127
    15  AppKit                              0x00007fff8ab3a12d -[NSTextInputContext do_HandleTSMEvent_insertFixLenTextLoop:whileCondition:dispatchWorkEach:afterEachInsertText:continuation:] + 170
    16  AppKit                              0x00007fff8b0f653e -[NSTextInputContext tryHandleTSMEvent_insertFixLenText_withContext:dispatchCondition:setupForDispatch:nestedWorkaroundCondition:nestedWorkaroundDispatchWork:loopCondition:dispatchWorkEach:afterEachInsertText:continuation:] + 377
    17  AppKit                              0x00007fff8ab39b76 __55-[NSTextInputContext handleTSMEvent:completionHandler:]_block_invoke174 + 3779
    18  AppKit                              0x00007fff8ab38bff -[NSTextInputContext(NSInputContext_WithCompletion) hasMarkedTextWithCompletionHandler:] + 76
    19  AppKit                              0x00007fff8ab38ba0 __55-[NSTextInputContext handleTSMEvent:completionHandler:]_block_invoke_2 + 95
    20  AppKit                              0x00007fff8ab38b18 -[NSTextInputContext tryHandleTSMEvent_HasMarkedText_withDispatchCondition:dispatchWork:continuation:] + 101
    21  AppKit                              0x00007fff8ab387d5 -[NSTextInputContext handleTSMEvent:completionHandler:] + 3122
    22  AppKit                              0x00007fff8ab37b2e _NSTSMEventHandler + 324
    23  HIToolbox                           0x00007fff8c691b6c _ZL23DispatchEventToHandlersP14EventTargetRecP14OpaqueEventRefP14HandlerCallRec + 1260
    24  HIToolbox                           0x00007fff8c690fae _ZL30SendEventToEventTargetInternalP14OpaqueEventRefP20OpaqueEventTargetRefP14HandlerCallRec + 386
    25  HIToolbox                           0x00007fff8c690e22 SendEventToEventTargetWithOptions + 43
    26  HIToolbox                           0x00007fff8c6f526c SendTSMEvent_WithCompletionHandler + 417
    27  HIToolbox                           0x00007fff8c6f576c __SendUnicodeTextAEToUnicodeDoc_WithCompletionHandler_block_invoke + 400
    28  HIToolbox                           0x00007fff8c6f55a6 __SendFilterTextEvent_WithCompletionHandler_block_invoke + 189
    29  HIToolbox                           0x00007fff8c6f52c0 SendTSMEvent_WithCompletionHandler + 501
    30  HIToolbox                           0x00007fff8c6f508f SendFilterTextEvent_WithCompletionHandler + 236
    31  HIToolbox                           0x00007fff8c6f4d51 SendUnicodeTextAEToUnicodeDoc_WithCompletionHandler + 295
    32  HIToolbox                           0x00007fff8c6f4ae9 __utDeliverTSMEvent_WithCompletionHandler_block_invoke_2 + 296
    33  HIToolbox                           0x00007fff8c6f4988 __utDeliverTSMEvent_WithCompletionHandler_block_invoke + 437
    34  HIToolbox                           0x00007fff8c6f47cd TSMKeyEvent_WithCompletionHandler + 701
    35  HIToolbox                           0x00007fff8c6f44d0 __TSMProcessRawKeyEventWithOptionsAndCompletionHandler_block_invoke_4 + 251
    36  HIToolbox                           0x00007fff8c6f4386 __TSMProcessRawKeyEventWithOptionsAndCompletionHandler_block_invoke_3 + 330
    37  HIToolbox                           0x00007fff8c6f4112 __TSMProcessRawKeyEventWithOptionsAndCompletionHandler_block_invoke_2 + 259
    38  HIToolbox                           0x00007fff8c6f3f25 __TSMProcessRawKeyEventWithOptionsAndCompletionHandler_block_invoke + 251
    39  HIToolbox                           0x00007fff8c6d876f TSMProcessRawKeyEventWithOptionsAndCompletionHandler + 3068
    40  AppKit                              0x00007fff8b0fce86 __61-[NSTextInputContext _handleEvent:options:completionHandler:]_block_invoke949 + 131
    41  AppKit                              0x00007fff8ab36352 -[NSTextInputContext tryTSMProcessRawKeyEvent:dispatchCondition:setupForDispatch:furtherCondition:dispatchWork:continuation:] + 127
    42  AppKit                              0x00007fff8ab36085 -[NSTextInputContext _handleEvent:options:completionHandler:] + 1266
    43  AppKit                              0x00007fff8ab35b4e -[NSTextInputContext handleEvent:] + 109
    44  AppKit                              0x00007fff8ab35a54 -[NSView interpretKeyEvents:] + 207
    45  AppKit                              0x00007fff8ab3586a -[NSTextView keyDown:] + 695
    46  AppKit                              0x00007fff8b0250fb -[NSWindow _reallySendEvent:isDelayedEvent:] + 5452
    47  AppKit                              0x00007fff8a9b6c86 -[NSWindow sendEvent:] + 470
    48  AppKit                              0x00007fff8a9b38b1 -[NSApplication sendEvent:] + 4199
    49  AppKit                              0x00007fff8a8dcb68 -[NSApplication run] + 711
    50  AppKit                              0x00007fff8a859244 NSApplicationMain + 1832
    51  addobserver_test                    0x00000001000066cd main + 109
    52  libdyld.dylib                       0x00007fff91e0b5c9 start + 1
    53  ???                                 0x0000000000000003 0x0 + 3
)
2015-08-23 18:36:32.358 addobserver_test[52788:3477511] -[__NSCFString fieldTextChanged:]: unrecognized selector sent to instance 0x6000000c3720
2015-08-23 18:36:32.358 addobserver_test[52788:3477511] Exception detected while handling key input.
2015-08-23 18:36:32.358 addobserver_test[52788:3477511] -[__NSCFString fieldTextChanged:]: unrecognized selector sent to instance 0x6000000c3720
2015-08-23 18:36:32.361 addobserver_test[52788:3477511] (
    0   CoreFoundation                      0x00007fff8f2c003c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff9059576e objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff8f2c30ad -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
    3   CoreFoundation                      0x00007fff8f208e24 ___forwarding___ + 1028
    4   CoreFoundation                      0x00007fff8f208998 _CF_forwarding_prep_0 + 120
    5   CoreFoundation                      0x00007fff8f27c45c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    6   CoreFoundation                      0x00007fff8f16c634 _CFXNotificationPost + 3140
    7   Foundation                          0x00007fff8fcf0aa1 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
    8   CoreFoundation                      0x00007fff8f27c45c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    9   CoreFoundation                      0x00007fff8f16c634 _CFXNotificationPost + 3140
    10  Foundation                          0x00007fff8fcf0aa1 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
    11  AppKit                              0x00007fff8ab3deb1 -[NSTextView(NSSharing) didChangeText] + 348
    12  AppKit                              0x00007fff8ab3b13b -[NSTextView insertText:replacementRange:] + 2827
    13  AppKit                              0x00007fff8ab3a237 -[NSTextInputContext(NSInputContext_WithCompletion) insertText:replacementRange:completionHandler:] + 98
    14  AppKit                              0x00007fff8abf8932 -[NSKeyBindingManager(NSKeyBindingManager_MultiClients) flushTextForClient:] + 178
    15  AppKit                              0x00007fff8b0fd2ef __61-[NSTextInputContext _handleEvent:options:completionHandler:]_block_invoke972 + 460
    16  AppKit                              0x00007fff8ab38bff -[NSTextInputContext(NSInputContext_WithCompletion) hasMarkedTextWithCompletionHandler:] + 76
    17  AppKit                              0x00007fff8ab50d03 __61-[NSTextInputContext _handleEvent:options:completionHandler:]_block_invoke_3 + 95
    18  AppKit                              0x00007fff8ab49ed8 -[NSTextInputContext tryHandleEvent_HasMarkedText_withDispatchCondition:dispatchWork:continuation:] + 101
    19  AppKit                              0x00007fff8b0fd074 __61-[NSTextInputContext _handleEvent:options:completionHandler:]_block_invoke960 + 321
    20  HIToolbox                           0x00007fff8c6f8d4f __TSMProcessRawKeyEventWithOptionsAndCompletionHandler_block_invoke_5 + 70
    21  HIToolbox                           0x00007fff8c6f52c0 SendTSMEvent_WithCompletionHandler + 501
    22  HIToolbox                           0x00007fff8c6f576c __SendUnicodeTextAEToUnicodeDoc_WithCompletionHandler_block_invoke + 400
    23  HIToolbox                           0x00007fff8c6f55a6 __SendFilterTextEvent_WithCompletionHandler_block_invoke + 189
    24  HIToolbox                           0x00007fff8c6f52c0 SendTSMEvent_WithCompletionHandler + 501
    25  HIToolbox                           0x00007fff8c6f508f SendFilterTextEvent_WithCompletionHandler + 236
    26  HIToolbox                           0x00007fff8c6f4d51 SendUnicodeTextAEToUnicodeDoc_WithCompletionHandler + 295
    27  HIToolbox                           0x00007fff8c6f4ae9 __utDeliverTSMEvent_WithCompletionHandler_block_invoke_2 + 296
    28  HIToolbox                           0x00007fff8c6f4988 __utDeliverTSMEvent_WithCompletionHandler_block_invoke + 437
    29  HIToolbox                           0x00007fff8c6f47cd TSMKeyEvent_WithCompletionHandler + 701
    30  HIToolbox                           0x00007fff8c6f44d0 __TSMProcessRawKeyEventWithOptionsAndCompletionHandler_block_invoke_4 + 251
    31  HIToolbox                           0x00007fff8c6f4386 __TSMProcessRawKeyEventWithOptionsAndCompletionHandler_block_invoke_3 + 330
    32  HIToolbox                           0x00007fff8c6f4112 __TSMProcessRawKeyEventWithOptionsAndCompletionHandler_block_invoke_2 + 259
    33  HIToolbox                           0x00007fff8c6f3f25 __TSMProcessRawKeyEventWithOptionsAndCompletionHandler_block_invoke + 251
    34  HIToolbox                           0x00007fff8c6d876f TSMProcessRawKeyEventWithOptionsAndCompletionHandler + 3068
    35  AppKit                              0x00007fff8b0fce86 __61-[NSTextInputContext _handleEvent:options:completionHandler:]_block_invoke949 + 131
    36  AppKit                              0x00007fff8ab36352 -[NSTextInputContext tryTSMProcessRawKeyEvent:dispatchCondition:setupForDispatch:furtherCondition:dispatchWork:continuation:] + 127
    37  AppKit                              0x00007fff8ab36085 -[NSTextInputContext _handleEvent:options:completionHandler:] + 1266
    38  AppKit                              0x00007fff8ab35b4e -[NSTextInputContext handleEvent:] + 109
    39  AppKit                              0x00007fff8ab35a54 -[NSView interpretKeyEvents:] + 207
    40  AppKit                              0x00007fff8ab3586a -[NSTextView keyDown:] + 695
    41  AppKit                              0x00007fff8b0250fb -[NSWindow _reallySendEvent:isDelayedEvent:] + 5452
    42  AppKit                              0x00007fff8a9b6c86 -[NSWindow sendEvent:] + 470
    43  AppKit                              0x00007fff8a9b38b1 -[NSApplication sendEvent:] + 4199
    44  AppKit                              0x00007fff8a8dcb68 -[NSApplication run] + 711
    45  AppKit                              0x00007fff8a859244 NSApplicationMain + 1832
    46  addobserver_test                    0x00000001000066cd main + 109
    47  libdyld.dylib                       0x00007fff91e0b5c9 start + 1
    48  ???                                 0x0000000000000003 0x0 + 3
)

第一个问题是,我的选择器前面需要@objc 吗?我认为这不是必需的,因为 NSViewController 是 NSObject 的子 class,这似乎使 @objc 变得不必要。这是正确的吗?

我需要做什么才能完成这项工作?

我有一个示例测试项目:

https://github.com/ericgorr/addobserver_test

谢谢。

在您的 applicationDidFinishLaunching 中,您没有保留对视图控制器的引用,因此该对象会立即释放。然后将通知发送到另一个在内存中占据一席之地的对象(在本例中为 __NSCFString)。

您需要存储对视图控制器的强引用,例如作为实例变量。