Objective c 当我们执行NSTimer无效时发生了什么?
然后应用程序崩溃,因为Objective c 当我们执行NSTimer无效时发生了什么?,objective-c,cocoa,nstimer,Objective C,Cocoa,Nstimer,然后应用程序崩溃,因为EXC\u访问错误 苹果的文件说 此方法是从nsrunlop对象中删除计时器的唯一方法。NSRunLoop对象在invalidate方法返回之前或稍后某个时间删除对计时器的强引用。如果它配置了目标和用户信息对象,接收器也会删除对这些对象的强引用。 苹果告诉我们在计时器失效后不要使用userInfo,但为什么呢 计时器的引用计数由程序员控制,userInfo(我尝试将属性用作userInfo,而不是使用常量字符串)也是一样的 如果我们放置一个符号断点,比如-[NSTimer
EXC\u访问错误
苹果的文件说
此方法是从nsrunlop对象中删除计时器的唯一方法。NSRunLoop对象在invalidate方法返回之前或稍后某个时间删除对计时器的强引用。如果它配置了目标和用户信息对象,接收器也会删除对这些对象的强引用。
苹果告诉我们在计时器失效后不要使用userInfo
,但为什么呢
计时器的引用计数由程序员控制,userInfo(我尝试将属性用作userInfo,而不是使用常量字符串)也是一样的
如果我们放置一个符号断点,比如-[NSTimer userinfo]
,我们可以得到崩溃信息,比如
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(timeCall:) userInfo:self.strong repeats:YES];
[self.timer invalidate];
NSLog(@"%p",[self.timer userInfo]);
CoreFoundation`-[\uu NSCFTimer userInfo]:
0x7fff20384d32:pushq%rbp
0x7fff20384d33:movq%rsp%rbp
0x7fff20384d36:pushq%rbx
0x7fff20384d37:subq$0x38,%rsp
0x7fff20384d3b:movq 0x5fca7d6e(%rip),%rax;(无效*)0x00007fff86d060e0:uu堆栈_uchk_u保护
0x7fff20384d42:movq(%rax),%rax
0x7fff20384d45:movq%rax,-0x10(%rbp)
0x7fff20384d49:leaq-0x38(%rbp),%rbx
0x7fff20384d4d:movq$0x0,(%rbx)
0x7fff20384d54:movq%rbx%rsi
0x7fff20384d57:调用0x7fff203a6ff9;CFRunLoopTimerGetContext
0x7fff20384d5c:movq 0x8(%rbx),%rax
->0x7fff20384d60:movq 0x18(%rax),%rax
0x7fff20384d64:movq 0x5fca7d45(%rip),%rcx;(无效*)0x00007fff86d060e0:uu堆栈_uchk_u保护
0x7fff20384d6b:movq(%rcx),%rcx
0x7fff20384d6e:cmpq-0x10(%rbp),%rcx
0x7fff20384d72:jne 0x7fff20384d7b;
0x7fff20384d74:addq$0x38,%rsp
0x7fff20384d78:popq%rbx
0x7fff20384d79:popq%rbp
0x7fff20384d7a:retq
0x7fff20384d7b:callq 0x7fff204c318e;符号存根:\堆栈\通道\失败
我知道nsrunlop和NSTimer之间的关系,但是这个userinfo属性呢?我想可能是为了存档
只读
关键字。我们如何研究NSTimer
的内部实现,或者有什么方法可以探索呢?如果它配置了目标和用户信息对象,接收器也会删除对这些对象的强引用。
因此self.timer为零,并且没有对userInfo的引用。self.timer
表示您使用NSTimer
创建了一个属性。设置内部\u定时器=nil有帮助代码>紧接着[self.timer invalidate]代码>。如果(!\u timer)self.timer=[NSTimer scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:],它将帮助在self.timer上重新应用新的NSTimer代码>从手册中,我希望userInfo
的指针最坏情况是,如果发布了,就返回0。虽然userInfo
被定义为头文件中的一个属性,但我从崩溃转储中怀疑,它实际上是一条带有礼貌检查的消息,抛出了该异常,或者-gasp-一个可怕的错误。由于消息似乎调用了CFRunLoopTimerGetContext
,您需要预先分配内存,我想可能只是一个bug。尽管如此,使用无效的计时器做任何事情都不会赢得框架上众多bug修复者的同情。@OlSen,在我编辑这个问题时,计时器的引用计数和userInfo的引用计数都是由程序员控制的。userInfo
属性是-[\u\nschftimer userInfo]
的语法糖。显然,userInfo
存储在上下文的info
中,并且invalidate
删除此info
。计时器没有指向invalidate
之后的userInfo
对象的指针。
CoreFoundation`-[__NSCFTimer userInfo]:
0x7fff20384d32 <+0>: pushq %rbp
0x7fff20384d33 <+1>: movq %rsp, %rbp
0x7fff20384d36 <+4>: pushq %rbx
0x7fff20384d37 <+5>: subq $0x38, %rsp
0x7fff20384d3b <+9>: movq 0x5fca7d6e(%rip), %rax ; (void *)0x00007fff86d060e0: __stack_chk_guard
0x7fff20384d42 <+16>: movq (%rax), %rax
0x7fff20384d45 <+19>: movq %rax, -0x10(%rbp)
0x7fff20384d49 <+23>: leaq -0x38(%rbp), %rbx
0x7fff20384d4d <+27>: movq $0x0, (%rbx)
0x7fff20384d54 <+34>: movq %rbx, %rsi
0x7fff20384d57 <+37>: callq 0x7fff203a6ff9 ; CFRunLoopTimerGetContext
0x7fff20384d5c <+42>: movq 0x8(%rbx), %rax
-> 0x7fff20384d60 <+46>: movq 0x18(%rax), %rax
0x7fff20384d64 <+50>: movq 0x5fca7d45(%rip), %rcx ; (void *)0x00007fff86d060e0: __stack_chk_guard
0x7fff20384d6b <+57>: movq (%rcx), %rcx
0x7fff20384d6e <+60>: cmpq -0x10(%rbp), %rcx
0x7fff20384d72 <+64>: jne 0x7fff20384d7b ; <+73>
0x7fff20384d74 <+66>: addq $0x38, %rsp
0x7fff20384d78 <+70>: popq %rbx
0x7fff20384d79 <+71>: popq %rbp
0x7fff20384d7a <+72>: retq
0x7fff20384d7b <+73>: callq 0x7fff204c318e ; symbol stub for: __stack_chk_fail