问题
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(timeCall:) userInfo:self.strong repeats:YES];
[self.timer invalidate];
NSLog(@"%p",[self.timer userInfo]);
Then app crashes because EXC_BAD_ACCESS
.
Apple document says,
This method is the only way to remove a timer from an NSRunLoop object. The NSRunLoop object removes its strong reference to the timer, either just before the invalidate method returns or at some later point. If it was configured with target and user info objects, the receiver removes its strong references to those objects as well.
And Apple tells us not to use userInfo
after a timer invalidate.But why?
The timer's refrence count is controlled by programmer,and also the userInfo(I tried use property as userInfo,instead of using constant string),the result is the same.
If we put a symbol breakpoint like -[NSTimer userinfo]
,we can get crash info like
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
I know the relationship between NSRunloop and NSTimer,but what about this userinfo property?Maybe it's for archiving the readonly
keyword,I guess.How can we look into the internel implementation of NSTimer
or is there a way to explore?
来源:https://stackoverflow.com/questions/64662272/what-happed-when-we-excute-nstimer-invalidate