[__NSCFTimer copyWithZone:]:无法识别的选择器发送到实例

Posted

技术标签:

【中文标题】[__NSCFTimer copyWithZone:]:无法识别的选择器发送到实例【英文标题】:[__NSCFTimer copyWithZone:]: unrecognized selector sent to instance 【发布时间】:2014-08-23 11:02:25 【问题描述】:
    var searchDelayer:NSTimer?
    func searchBar(searchBar: UISearchBar!, textDidChange searchText: String!) 
        searchDelayer?.invalidate()
        searchDelayer = nil

        searchDelayer = NSTimer.scheduledTimerWithTimeInterval(1.5, target: self, selector: Selector("doDelayedSearch:"), userInfo: searchText, repeats: false)

    

    func doDelayedSearch(text:String)
    ...
    

为什么这段代码会崩溃并显示错误消息:

[__NSCFTimer copyWithZone:]: unrecognized selector sent to instance

更新:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFTimer copyWithZone:]: unrecognized selector sent to instance 0x7f9c622ae7e0'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010c05b3e5 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010ba42967 objc_exception_throw + 45
    2   CoreFoundation                      0x000000010c0624fd -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
    3   CoreFoundation                      0x000000010bfba7ec ___forwarding___ + 988
    4   CoreFoundation                      0x000000010bfba388 _CF_forwarding_prep_0 + 120
    5   CoreFoundation                      0x000000010bf32935 CFStringCreateCopy + 229
    6   libswiftFoundation.dylib            0x000000010dc41314 _TF10Foundation24_convertNSStringToStringFCSo8NSStringSS + 116
    7   MapCode                             0x000000010a1a567e _TToFC7MapCode17MapViewController15doDelayedSearchfS0_FSST_ + 62
    8   Foundation                          0x000000010b5fce94 __NSFireTimer + 83
    9   CoreFoundation                      0x000000010bfc34d4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
    10  CoreFoundation                      0x000000010bfc3095 __CFRunLoopDoTimer + 1045
    11  CoreFoundation                      0x000000010bf863cd __CFRunLoopRun + 1901
    12  CoreFoundation                      0x000000010bf859f6 CFRunLoopRunSpecific + 470
    13  GraphicsServices                    0x000000010ecfd9f0 GSEventRunModal + 161
    14  UIKit                               0x000000010c96b990 UIApplicationMain + 1282
    15  MapCode                             0x000000010a1b3fee top_level_code + 78
    16  MapCode                             0x000000010a1b402a main + 42
    17  libdyld.dylib                       0x000000010f9d7145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

【问题讨论】:

我已经删除了我的答案,因为它显然没有帮助。 - 再想一想,问题一定是和定时器本身有关,而不是和目标有关。能否设置一个“异常断点”,然后在异常发生时发布堆栈回溯? @MartinR 谢谢。请查看更新后的帖子。当设置异常断点时,应用程序在 AppDelegate.swift 中崩溃,在线 class AppDelegate: UIResponder, UIApplicationDelegate 您能否在调试器中单步执行并验证导致崩溃的行。堆栈跟踪看起来好像在 doDelayedSearch 内部,试图复制一个字符串并找到一个意外的计时器对象。 定时器回调不能有String 参数。将在一分钟内更新我的答案... 啊......那么它认为它在CFStringCreateCopy + 229复制的字符串可能是输入参数。 【参考方案1】:

定时器回调函数必须是不带参数的函数,或者 将NSTimer 作为单个参数的函数。

在你的情况下,应该是

func doDelayedSearch(timer: NSTimer) 
    let searchText = timer.userInfo as String
    // ...


旧答案:(以下正确,但不适用于此处)

计时器的目标(在您的情况下为self)需要与Objective-C兼容, 即源自NSObject 或标记为@objc

另请参阅 Exposing Swift Interfaces in Objective-C 在 “将 Swift 与 Cocoa 和 Objective-C 结合使用”文档(重点是我的):

@objc 属性使您的 Swift API 在 Objective-C 和 Objective-C 运行时。换句话说,您可以使用@objc 任何 Swift 方法、属性、下标、初始值设定项之前的属性, 或要从 Objective-C 代码中使用的类。如果你的班级 从Objective-C类继承,编译器插入属性 给你。 ... 此属性在您使用时也很有用 Objective-C 类使用选择器来实现目标动作设计模式,例如NSTimerUIButton

【讨论】:

在我的例子中,self属于UIViewController类。我将其标记为@objc,但仍然会发生崩溃。

以上是关于[__NSCFTimer copyWithZone:]:无法识别的选择器发送到实例的主要内容,如果未能解决你的问题,请参考以下文章

如何解决“[_NSCFTimer login:]:unrecognized selector sent to instance 的错误

Objective-C笔记大全

iPhone:copyWithZone:在返回之前释放一个对象?

NSInvalidArgumentException/copyWithZone 异常与 NSMutableDictionary

如何使用 copyWithZone 进行深层复制以复制结构?

错误:静态成员 copyWithZone 不能用于 UIImageView 类型的实例