2015-04-30 28 views
5

içinde çökmesini önleme Bizim app UICollectionView vardır ve dataSource sözlüğü düzenli olarak güncellenir. Bir sonraki güncellemenin ne zaman olacağını asla bilemeyiz. Kullanıcı bir düğmeyi tıkladığında veya ağ isteği başarısından sonra eşzamansız hale geldikten sonra Koleksiyon Görüntüleme yeniden yükleme yöntemi çağrılabilir. Yukarıdaki bilgiler ışığında, toplama görünümünü yeniden yüklerken ve aynı zamanda veri kaynağını güncellerken bir yarış koşuluna sahip olma riskine sahibiz. Aşağıdaki çökmeyi bile kaydettik ve bunun yukarıda açıklanan yarış durumu nedeniyle gerçekleştiğine inanıyoruz. çarpışma mesajı:UICollectionView

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]' 

çökmesine neden yöntemi: collectionViewLayout sizeForItemAtIndexPath:.

Bu yöntem, sectionWithProducts numaralı belgede yer alan öğelerin sayısına bağlı olarak koleksiyonun görünümü için yüksekliği hesaplar. dataSource sayısı indexPath.row'dan daha küçük olduğundan çöküyor. Ve çizgi çökmesine neden: Kazadan önce denilen izinde giden

NSArray *sectionWithProducts = self.dataSource[indexPath.row];

oldu:

[self.collectionView setCollectionViewLayout:[self flowLayout] animated:NO]; 
[self.collectionView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO]; 
[self.collectionView reloadData]; 

biz ana iş parçacığı içine kod sadece çizgi güncellemeleri veri kaynağı koymaya karar Bunu önlemek için.

// Always run on main thread in hope to prevent NSRangeException. 
// Reloading data should happen only sequential. 
dispatch_async(dispatch_get_main_queue(), ^(void) { 
    self.dataSource = newValue; 
}); 

Bizim kodunda [self.collectionView reloadData] bir sürü vardı. Onları ana iş parçasında da çalıştırmaya değer mi? Hızlı bir şekilde gerçekleşti, dolayısıyla UI'yi uzun süre engellememeli.

indexPath ile temsilci yöntemleri her zaman arka plan sırasına çağrılır mı?

cevap

0

Her şeyden önce, tüm UIKIT yöntemleri, reloadData dahil olmak üzere ana iş parçacığına çağrılmalıdır. Ancak bu, çökmenizi çözmeyecektir. İkincisi, kodunuzda bir yerde reloadData çağıracağınız ve aynı anda veri kaynağını değiştirebileceğiniz bir yarış durumu var ve bunun nerede olduğunu anlamanız gerekiyor. Bu, gerçek kodu görmeden söyleyebileceğim şey.