3

这个错误已经在我的代码中好几天了——我一直在尝试解决它,但无济于事。我已经在模拟器和设备上进行了广泛的调试,日志记录,Crashlytics 抛出崩溃日志,这与我NSTimer在释放后被发送消息有关。我会进一步解释。

NSTimer控制了我UIToolbar在某些视图控制器上的标签,并不断更新标签以显示从用户刷新UITableView. 加载时,每次刷新时,它都会显示Updated just now,然后如果用户不刷新/转到另一个 VC,它会每 60 秒更新一次。所以,一分钟后,它会显示Updated 1 minute agoNSTimer触发执行UILabel更新的方法。在用户刷新时(通过拉动刷新控件),在我的内部手动调用此方法getAllItems(这就是我通过的原因nil)。

MyNSTimer在我的超类中定义为:

@property (nonatomic, weak) NSTimer *updateDateTimer;

这是将项目放入我的表格视图的代码:

- (void)getAllItems
{
    KILL_TIMER(self.updateDateTimer);
    self.updateLabel = [Formatters boldLabelWithLabel:self.updateLabel
                                             withText:@"Checking for items..."
                                             withFont:[UIFont fontWithName:kOpenSansBold size:15.0f]];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self fetchObjectsWithRequest:self.request];
        sleep(1);
        dispatch_async(dispatch_get_main_queue(), ^{
                [self.refreshControl performSelector:@selector(endRefreshing) withObject:nil afterDelay:0];

            self.updatedDate = [NSDate date];
            [self updateTimer:nil];
            self.updateDateTimer = [NSTimer scheduledTimerWithTimeInterval:kToolbarUpdateLabelInterval
                                                                    target:self
                                                                  selector:@selector(updateTimer:)
                                                                  userInfo:nil repeats:YES];
        });
    });
}

KILL_TIMER(q)在我的超类中定义为:

#define KILL_TIMER(q) if (q) {DDLogVerbose(@"KILLING TIMER: %@", q); [q invalidate]; q=nil;}

此定义在 2 种方法中调用:

a) 在我的getAllItems方法中:所以当我(重新)加载项目(通过调用该方法viewDidLoad或通过用户刷新表格视图)时,我总是尝试终止当前处于活动状态的计时器,显示“检查项目”,获取项目,显示“刚刚更新”,然后安排计时器每 60 秒执行一次。

b) 在每个 viewWillDisappear 上,例如:

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    KILL_TIMER(self.updateDateTimer);
}

但是,如果我点击主页按钮,然后重新打开应用程序,它通常(并非总是,仅当我切换视图控制器时)崩溃并显示以下消息(启用 NSZombies):

2013-07-11 17:21:37.576 App[3923:907] *** -[ItemCDTVC setUpdateDateTimer:]: message sent to deallocated instance 0x20bc49f0

我确实有一个NSNotification调用我的getAllItems

// Notification received when user returns to app (refreshes the table view)
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getAllItems) name:UIApplicationWillEnterForegroundNotification object:nil];

这只发生在我使用菜单切换视图控制器、离开应用程序并重新打开(应用程序不会终止)之后。如果用户留在应用程序中,无论他们在多少个视图控制器之间切换,它都不会崩溃。

这是一个非常烦人的错误,因为虽然它很容易重现,但我不知道如何修复它。任何帮助表示赞赏。

4

2 回答 2

4

当您的应用程序变为非活动状态时,您应该使计时器无效-applicationWillResignActive:是这样做的好地方。当应用再次激活时,您可以创建新的计时器。

有根据的猜测是您的应用程序正在崩溃,因为当应用程序处于非活动状态时计时器会自动终止,然后当您的应用程序返回前台并尝试访问不再有效的计时器时您会崩溃。

于 2013-07-11T17:13:39.390 回答
2

一旦你在定时器上调用 invalidate ,你就不能再次使用它 -如何在 NSTimer 失效后“验证”它?

如果我想要一个可以随意“打开/关闭”的计时器,我会使用一个BOOL useTimer或类似的东西来决定计时器是否应该触发,用于重复计时器。

对于非重复计时器,我创建了一个新计时器。

于 2013-07-11T17:14:13.250 回答