NSTimer不会失效

Con*_*lor 1 cocoa-touch objective-c nstimer

这里的代码不多,但这个问题让我非常讨厌!

.H:

@interface processController : UIViewController {
         NSTimer *timer;
}
@property (nonatomic, retain) NSTimer *timer;
Run Code Online (Sandbox Code Playgroud)

.M:

- (void)viewDidLoad {
    [super viewDidLoad];
    timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector (main) userInfo:nil repeats:YES];
}
- (void)main {
    NSLog(@"testing");
}
- (void)viewDidUnload {
    [self.timer invalidate];
    self.timer = nil;
}
Run Code Online (Sandbox Code Playgroud)

奇怪的是,当我解雇这段代码时:

ViewController *main = [[ViewController alloc] initWithNibName:nil bundle:nil];
    [self presentModalViewController:main animated:YES];
Run Code Online (Sandbox Code Playgroud)

和切换视图,计时器一直开火!我究竟做错了什么?

Pie*_*ard 5

viewDidUnload从视图中删除视图时不会调用,但在应用程序收到内存警告时才会调用.当UIViewController被释放时也不会调用它.来自Apple的文档:

当发生内存不足的情况并且不需要当前视图控制器的视图时,系统可以选择从内存中删除这些视图.在视图控制器的视图发布后调用此方法,并且您有机会执行任何最终清理.如果视图控制器存储对视图或其子视图的单独引用,则应使用此方法来释放这些引用.您还可以使用此方法删除对您为支持视图而创建的任何对象的引用,但现在视图已不再使用.您不应使用此方法来释放用户数据或任何其他无法轻松重新创建的信息.

你很可能打算使用 viewWillDisappear

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [self.timer invalidate];
    self.timer = nil;
}   
Run Code Online (Sandbox Code Playgroud)

您可能希望在viewWillAppear中启动计时器:因为只要访问控制器的视图属性就会调用viewDidLoad.显示视图时并不是必然的.

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(main) userInfo:nil repeats:YES];
}
Run Code Online (Sandbox Code Playgroud)

我建议从UIViewController文档中阅读viewDidLoad和viewDidUnload以及viewWillAppear和viewWillDisappear的讨论.

  • 是的,重要的是要注意,当你的VC被解除分配时,甚至都没有调用viewDidUnload,它实际上只是*当你的VC仍在*时,*你的视图是在屏幕外,然后操作系统发送低内存(或类似的情况) ).根据我的经验,这只是我在导航层次结构中更深2或3级并模拟低内存. (2认同)