3

このバグは私のコードに何日もありました - 私はそれを解決しようとしましたが、役に立ちませんでした. シミュレーターとデバイス、ログ、Crashlytics がクラッシュ ログをスローする広範なデバッグを行いました。これは、NSTimer割り当て解除後にメッセージが送信されたことに関係しています。さらに説明します。

これにより、一部のビュー コントローラーでラベルがNSTimer制御され、UIToolbarラベルが更新され続けて、ユーザーがUITableView. 読み込み時、および更新のたびに表示さUpdated just nowれ、ユーザーが更新しない/別の VC に移動しない場合、60 秒ごとに更新され続けます。そのため、1 分後に が表示されUpdated 1 minute agoます。は、更新NSTimerを行うメソッドをトリガーします。UILabelユーザーが更新すると (更新コントロールをプルすることによって)、このメソッドは my 内で手動で呼び出されます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か、ユーザーがテーブル ビューを更新することによって)、常にアクティブな現在のタイマーを強制終了し、「アイテムのチェック」を表示し、アイテム、'updated just now' を表示し、タイマーを 60 秒ごとに実行するようにスケジュールします。

b)各viewWillDisappear`で、次のように:

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

ただし、ホームボタンを押してアプリを再度開くと、通常は (常にではありませんが、View Controller を切り替えた場合のみ)、次のメッセージが表示されてクラッシュします (NSZombies が有効になっている場合)。

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

NSNotificationは my を呼び出すを持っていますgetAllItems:

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

これは、メニューを使用してView Controllerを切り替え、アプリを終了して再度開いた後にのみ発生します(アプリは終了しません)。ユーザーが切り替えたView Controllerの数に関係なく、ユーザーがアプリにとどまってもクラッシュしません。

非常に厄介なバグです。非常に簡単に再現できますが、修正方法がわからないからです。どんな助けでも大歓迎です。

4

2 に答える 2