考虑具有强(或弱,相同)NSTimer
属性的视图控制器:
__weak __typeof(self) ws = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:ws selector:@selector(timerTigger:) userInfo:nil repeats:YES];
但是为什么这个视图控制器不会调用dealloc
方法,我是否将strong
或weak
引用传递给self
?
以下是详细代码:
#import "SecondViewController.h"
@interface SecondViewController ()
@property (nonatomic, weak) NSTimer *timer;
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
__weak __typeof(self) ws = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:ws selector:@selector(timerTigger:) userInfo:nil repeats:YES];
}
- (void)timerTigger:(id)timer {
NSLog(@"do someting");
}
- (void)dealloc {
NSLog(@"SecondViewController dealloc");
}
答案 0 :(得分:10)
NSTimer
保持对其target
的强引用,直到计时器失效。您无法选择NSTimer
是建立弱引用还是强引用。当您传递弱引用时,只要ws
在启动计时器时不nil
(在这种情况下显然不会是NSTimer
),target
将会建立强烈引用scheduledTimerWithTimeInterval
指向的任何内容。 NSTimer
是建立强引用还是弱引用不是您传递给它的指针的一些固有特性,而是该方法对它所提供的指针的作用的问题。
要修复此强引用行为,您可以采用以下模式之一:
使用@interface ViewController ()
@property (nonatomic, weak) NSTimer *timer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
typeof(self) __weak weakSelf = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:2 repeats:true block:^(NSTimer * _Nonnull timer) {
[weakSelf timerTigger];
}];
}
- (void)timerTigger {
NSLog(@"do something");
}
- (void)dealloc {
[self.timer invalidate];
}
@end
的基于块的再现,并在块内使用“弱自我”模式;
@interface ViewController ()
@property (nonatomic, strong) dispatch_source_t timer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
typeof(self) __weak weakSelf = self;
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
dispatch_source_set_event_handler(self.timer, ^{
[weakSelf timerTigger];
});
dispatch_resume(self.timer);
}
- (void)timerTigger {
NSLog(@"do something");
}
@end
使用GCD计时器,它也是基于块的,因此也可以很容易地配置为不保持强引用;或
NSTimer
将invalidate
与目标/选择器一起使用,但viewDidDisappear
计时器位于某个逻辑位置(例如@interface ViewController ()
@property (nonatomic, weak) NSTimer *timer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerTigger:) userInfo:nil repeats:true];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self.timer invalidate];
}
- (void)timerTigger:(NSTimer *)timer {
NSLog(@"do something");
}
@end
等)。
#include<stdio.h>
int main(void)
{
printf("Minimum Signed Char %d\n",-(char)((unsigned char) ~0 >> 1) - 1);
printf("Maximum Signed Char %d\n",(char) ((unsigned char) ~0 >> 1));
printf("Minimum Signed Short %d\n",-(short)((unsigned short)~0 >>1) -1);
printf("Maximum Signed Short %d\n",(short)((unsigned short)~0 >> 1));
printf("Minimum Signed Int %d\n",-(int)((unsigned int)~0 >> 1) -1);
printf("Maximum Signed Int %d\n",(int)((unsigned int)~0 >> 1));
printf("Minimum Signed Long %ld\n",-(long)((unsigned long)~0 >>1) -1);
printf("Maximum signed Long %ld\n",(long)((unsigned long)~0 >> 1));
/* Unsigned Maximum Values */
printf("Maximum Unsigned Char %d\n",(unsigned char)~0);
printf("Maximum Unsigned Short %d\n",(unsigned short)~0);
printf("Maximum Unsigned Int %u\n",(unsigned int)~0);
printf("Maximum Unsigned Long %lu\n",(unsigned long)~0);
return 0;
}
答案 1 :(得分:-1)
你可以试试这个:
@interface Person : NSObject
@property(nonatomic, strong) DemoViewController_19 *vc;
@end
@implementation Person
@end
@interface DemoViewController_19 ()
@property(nonatomic, strong) Person *person;
@end
@implementation DemoViewController_19
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.person = [Person new];
__weak typeof(self) weaks = self;
self.person.vc = weaks;
}
@end
运行后可以看到没有调用vc dealloc。这取决于Person 的强属性属性。