NSTimer自我弱;为什么没有叫dealloc?

时间:2017-03-21 14:39:33

标签: ios objective-c nstimer dealloc

考虑具有强(或弱,相同)NSTimer属性的视图控制器:

__weak __typeof(self) ws = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:ws selector:@selector(timerTigger:) userInfo:nil repeats:YES];

但是为什么这个视图控制器不会调用dealloc方法,我是否将strongweak引用传递给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");
}

2 个答案:

答案 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 的强属性属性。