我剛剛完成調試一個非常討厭的UIViewController
泄漏,這樣即使在調用dismissViewControllerAnimated
之後UIViewController也不會被釋放。爲什麼在performBatchUpdates中對父UIViewController的強引用泄漏了一個活動?
我的問題追查到下面的代碼塊:
self.dataSource.doNotAllowUpdates = YES;
[self.collectionView performBatchUpdates:^{
[self.collectionView reloadItemsAtIndexPaths:@[indexPath]];
} completion:^(BOOL finished) {
self.dataSource.doNotAllowUpdates = NO;
}];
基本上,如果我做一個呼叫performBatchUpdates
後立即調用dismissViewControllerAnimated
的UIViewController中被泄露和UIViewController
的dealloc
方法不會被調用。 UIViewController永遠掛起。
有人可以解釋這種行爲嗎?我假設performBatchUpdates
運行一段時間間隔,比如500毫秒,所以我會假設在所述間隔之後,它會調用這些方法,然後觸發dealloc。
的修復似乎是這樣的:
self.dataSource.doNotAllowUpdates = YES;
__weak __typeof(self)weakSelf = self;
[self.collectionView performBatchUpdates:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf) {
[strongSelf.collectionView reloadItemsAtIndexPaths:@[indexPath]];
}
} completion:^(BOOL finished) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf) {
strongSelf.dataSource.doNotAllowUpdates = NO;
}
}];
注意,BOOL
成員變量,doNotAllowUpdates
,是我添加防止任何類型的數據源/的CollectionView更新到performBatchUpdates一個呼叫正在運行時的變量。
我在網上搜索了一下關於我們是否應該使用performBatchUpdates
中的weakSelf/strongSelf模式的討論,但沒有在這個問題上找到任何具體的內容。
我很高興能夠深入到這個bug的底部,但我更喜歡更聰明的iOS開發人員向我解釋我看到的這種行爲。
看看您是否可以確定是否導致保留週期的更新塊或完成塊,這會很有趣。正如你所說的,它們都不應該永久保留它們的塊 - 我只能假設當集合視圖從其超級視圖中被移除時,它將停止運行任何批量更新,並且不會調用或釋放完成塊。在我看來,值得雷達。 – jrturton
@jrturton啊這似乎是最有可能的解釋!基於這種見解,我會看看是否可以在調試器中重新制作這個代碼。 – esilver
@ jrturton alas無法在調試器中重現......看起來好像兩個塊至少總是被調用。也許內部不是無效的,雖然如果解僱被稱爲中間? – esilver