UICollectionView veri değişikliğini canlandırın


83

Projemde bir simge ızgarası görüntülemek için UICollectionView kullanıyorum.

Kullanıcı, farklı NSSortDescriptor ile çekirdek verilerden bir getirmeyi çağıran bölümlenmiş bir kontrole tıklayarak sıralamayı değiştirebilir.

Veri miktarı her zaman aynıdır, sadece farklı bölümler / satırlarla sonuçlanır:

- (IBAction)sortSegmentedControlChanged:(id)sender {

   _fetchedResultsController = nil;
   _fetchedResultsController = [self newFetchResultsControllerForSort];

   NSError *error;
   if (![self.fetchedResultsController performFetch:&error]) {
       NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
   }

   [self.collectionView reloadData];
}

Sorun, reloadData'nın değişikliğe animasyon vermemesidir, UICollectionView sadece yeni verilerle açılır.

Değişiklikten önce ve sonra bir hücrenin hangi indexPath'de olduğunu takip etmeli ve değişiklik için animasyonu gerçekleştirmek için [self.collectionView moveItemAtIndexPath: toIndexPath:] kullanmalı mıyım yoksa daha iyi bir yöntem mi var?

Koleksiyonun alt sınıflamasına pek girmedim, bu yüzden herhangi bir yardım harika olacak ...

Teşekkürler Bill.


Bu reloadDataaramayı bir animasyon bloğunda sarmayı denediniz mi?
simon

Yanıtlar:


72

reloadData canlandırmaz ve bir UIView animasyon bloğuna yerleştirildiğinde bunu güvenilir bir şekilde yapmaz. Bir UICollecitonView performBatchUpdates bloğunda olmak istiyor, bu nedenle aşağıdakilere benzer bir şey deneyin:

[self.collectionView performBatchUpdates:^{
    [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
} completion:^(BOOL finished) {
    // do something on completion 
}];

5
evet, bu işe yarıyor gibi görünüyor, ancak yalnızca bölüm numaralarını kaydetmişseniz ... yoksa "geçersiz sayıda bölüm alıyorum. Güncellemeden (10) sonra koleksiyon görünümünde bulunan bölüm sayısı, sayısına eşit olmalıdır güncellemeden önce koleksiyon görünümünde bulunan bölümler (16) ". Bölümleri elle eklemem / silmem gerekiyor ... yine de kabul! Teşekkürler.
Nimrod7

1
"El ile" derken, UICollectionView'ün insertSections / moveSection: toSection / deleteSections çağrılarını mı kastediyorsunuz? Veya başka bir şey? (üzgünüm, şimdiye kadar UICollectionView kullanımımda statik sayıda bölüm var)
Stripes

1
evet bu yöntemlerle ... düşünceyi uygulamak biraz zor, güncellemeden önce ve sonra dizin yollarını, kaldırılan veya taşınan şekli hatırlamanız gerekir ...
Nimrod7

12
Bu, tek bölümlük koleksiyon görünümüm için işe yaramadı. Ben hata almadım ama canlandırmadı. İkame -reloadSections:, çalışmasını sağlar.
paulmelnikow

9
Bu yanıt doğru değil, çünkü benim durumumda performBatchUpdates'e reloadData koyulması uygulamamı çökertecek ve hücre sayısının öncesi ve sonrası aynı olmadığını söyleyecektir. reloadSections kullanmak sorunumu çözdü. Apple'ın belgesi ayrıca animasyon bloğunda reloadData'nın çağrılmadığını da belirtir
Wingzero

145

Sarmalama -reloadData, -performBatchUpdates:tek bölümlük bir koleksiyon görünümünün hareketlenmesine neden olmuyor.

[self.collectionView performBatchUpdates:^{
    [self.collectionView reloadData];
} completion:nil];

Ancak, bu kod çalışır:

[self.collectionView performBatchUpdates:^{
    [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
} completion:nil];

9
Belgelerden not: Öğelerin eklendiği veya silindiği animasyon bloklarının ortasında yeniden yükleme veri yöntemini çağırmamalısınız. Eklemeler ve silmeler, otomatik olarak tablo verilerinin uygun şekilde güncellenmesine neden olur.
Raphael Oliveira

bence bu doğru cevap olmalı. çünkü bu benim için çalıştı. sadece 1 bölümüm var ve bu doğru cevap değil.
Mahesh Agrawal

Ayrıca ekliyorsanız çalışmaz. Sıralama animasyonunu geçersiz kılar.
Andres Canella

3
Animasyonu almak için self.collectionView performBatchUpdatesaramanın etrafına sarılmasına gerek olmadığını belirtmek gerekir reloadSections. Aslında performBatchUpdatesarama, bazı durumlarda yanlışlıkla titreme / hücre yeniden boyutlandırma sorunlarına neden olabilir.
Paul Popiel

1
Veya sadece [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]]; reloadSectionskoleksiyon görünümünde veya tablo görünümünde bunu animasyonla yapar.
bauerMusic

67

TÜM BÖLÜMLERİN yeniden yüklenmesini canlandırmak için yaptığım şey buydu:

[self.collectionView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.collectionView.numberOfSections)]];

Hızlı 3

let range = Range(uncheckedBounds: (0, collectionView.numberOfSections))
let indexSet = IndexSet(integersIn: range)
collectionView.reloadSections(indexSet)


3

Tüm koleksiyon görünümünü bir performBatchUpdates:completion:blok içinde yeniden yüklemek, benim için iOS 9 simülatöründe kusurlu bir animasyon oluşturur. UICollectionViewCellSilmek istediğiniz belirli bir şeyiniz varsa veya dizin yolunuz varsa deleteItemsAtIndexPaths:, o bloğu çağırabilirsiniz . Kullanarak deleteItemsAtIndexPaths:pürüzsüz ve hoş bir animasyon yapar.

UICollectionViewCell* cellToDelete = /* ... */;
NSIndexPath* indexPathToDelete = /* ... */;

[self.collectionView performBatchUpdates:^{
    [self.collectionView deleteItemsAtIndexPaths:@[[self.collectionView indexPathForCell:cell]]];
    // or...
    [self.collectionView deleteItemsAtIndexPaths:@[indexPath]];
} completion:nil];

1
Benim durumumda çökme sorununu çözen bir şeyden bahsetmek istiyorum, koleksiyon görünümünde performUpdates'i çağırmadan önce veri kaynağını (yani bölüm / öğe sayısı) güncelleyin.
ViruMax

Animasyon diğer operasyonlardandır; HERHANGİ BİR KOŞUL ALTINDA reloadData için bir animasyon vardır ve hiçbir zaman olmamıştır. insertItems artan sırada eklenir ve güncellemelerden SONRA gerçekleştirilir; deleteItems ise bunun tersidir.
James Bush

1

Yardım metni şunu söylüyor:

Koleksiyon görünümündeki tüm öğeleri yeniden yüklemek için bu yöntemi çağırın. Bu, koleksiyon görünümünün şu anda görünür olan öğeleri atmasına ve yeniden görüntülemesine neden olur. Verimlilik açısından koleksiyon görünümü yalnızca görünür olan hücreleri ve ek görünümleri görüntüler. Toplama verileri yeniden yüklemenin bir sonucu olarak küçülürse, koleksiyon görünümü kaydırma ofsetlerini buna göre ayarlar. Bu yöntemi, öğelerin eklendiği veya silindiği animasyon bloklarının ortasında çağırmamalısınız. Eklemeler ve silmeler, otomatik olarak tablo verilerinin uygun şekilde güncellenmesine neden olur.

Bence anahtar kısım "koleksiyon görünümünün şu anda görünür olan tüm öğeleri atmasına neden oluyor". Attığı eşyaların hareketini nasıl canlandıracak?


Kesinlikle öyle değil. reloadData, animasyonsuz, ikili bir işlemdir; bu önce bir silme işlemi, ardından bir ekleme işlemidir.
James Bush
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.