21

Tôi cần biết khi tải lại UICollectionView đã hoàn thành để định cấu hình các ô sau đó (vì tôi không phải là nguồn dữ liệu cho các ô - khác khôn ngoan đã làm được rồi. mã ..)Tải lại UICollectionView bằng cách sử dụng phương thức reloadData trả về ngay trước khi tải lại dữ liệu

tôi đã thử như

[self.collectionView reloadData]; 
[self configure cells]; // BOOM! cells are nil 

tôi cũng đã cố gắng sử dụng

[self.collectionView performBatchUpdates:^{ 
    [self.collectionView reloadData]; 
    } completion:^(BOOL finished) { 
     // notify that completed and do the configuration now 
    }]; 

nhưng khi tôi tải lại da ta đang bị treo.

Làm thế nào tôi có thể tải lại dữ liệu vào bộ sưu tập, và chỉ khi nó đã hoàn tất tải lại - làm một kết thúc xử lý đặc biệt

+0

Tôi nghĩ rằng tôi đã gặp vấn đề về simmilar. Vấn đề là các ô được nạp trong khi layoutSubview diễn ra trong lần chạy vòng lặp tiếp theo. Thật không may tôi đã không tìm thấy giải pháp nào được nêu ra. Tôi tự hỏi tại sao UICollectionViewDelegate không có phương pháp như: - collectionView: willBeginDisplayingCell: forItemAtIndexPath: trong khi có: - collectionView: didEndDisplayingCell: forItemAtIndexPath: bạn đã giải quyết một trong đó đã? – lukewar

+0

Điều xảy ra là khối cập nhật hàng loạt dự kiến ​​bạn thực hiện cuộc gọi để thêm và xóa hàng/phần tương ứng với số hàng và phần mới xảy ra trong khi tải lại. Nếu điều này không xảy ra, một khẳng định được ném. –

Trả lời

81

này được gây ra bởi các tế bào được thêm vào trong quá layoutSubviews không phải ở reloadData. Vì layoutSubviews được thực hiện trong lần chạy vòng lặp tiếp theo sau khi reloadData, các ô của bạn trống. Hãy thử thực hiện việc này:

[self.collectionView reloadData]; 
[self.collectionView layoutIfNeeded]; 
[self configure cells]; 

Tôi gặp vấn đề tương tự và giải quyết theo cách này.

+12

Câu trả lời hay phải được chấp nhận. –

+1

Tôi gặp vấn đề chính xác khi 'visibleCells' là 0 sau khi gọi' -reloadData'. Gọi '-layoutNếu đã được khắc phục 'đã sửa lỗi này. câu trả lời của lukewar phải được chấp nhận. –

+1

Hoàn hảo nhất. Nên được chấp nhận. –

5

Chế độ xem bộ sưu tập không được hỗ trợ tải lại động với sự trợ giúp của reloadData. Tất cả hoạt ảnh phải được thực hiện bằng các phương pháp, chẳng hạn như

[collectionView deleteItemsAtIndexPaths:indexesToDelete]; 
[collectionView insertSections:sectionsToInsert]; 
[collectionView reloadItemsAtIndexPaths:fooPaths]; 

bên trong khối performBatchUpdates:. Phương pháp reloadData chỉ có thể được sử dụng để làm mới thô, khi tất cả các mục được xóa và được trình bày lại mà không có hoạt ảnh.

+0

Tôi đã có một cuộc đua giữa kéo để làm mới và phản ứng api và điều này đã giúp. Tôi chỉ cần xóa và chèn các phần tôi muốn tải lại thay vì reloadData: 'self.collectionView? .performBatchUpdates ({ self.collectionView? .deleteSections (IndexSet (arrayLiteral: 0)) self.collectionView? .insertSections (IndexSet (arrayLiteral) : 0)) }, hoàn thành: nil) ' –

4

Nếu bạn muốn thực hiện một số mã sau collectionView của bạn đã hoàn thành nó reloadData() phương pháp, sau đó thử này (Swift):

self.collectionView.reloadData() 
    self.collectionView.layoutIfNeeded() 
    dispatch_async(dispatch_get_main_queue()) {() -> Void in 
     // Put the code you want to execute when reloadData is complete in here 
    } 

Lý do làm việc này là vì mã trong khối văn được đặt vào mặt sau của dòng (còn được gọi là hàng đợi). Điều này có nghĩa rằng nó đang chờ đợi trong dòng cho tất cả các hoạt động thread chính để kết thúc, bao gồm các phương thức reloadData(), trước khi nó trở thành nó bật chủ đề chính.

+1

tốt, điều này không hoàn toàn đúng, khối công văn có thể được chèn vào giữa một số hoạt động chủ đề chính, xem http://stackoverflow.com/a/10450867/4003774. Nhưng mã của bạn sẽ hoạt động (thậm chí không có dispatch_async) nhờ layoutIfNeeded (xem câu trả lời của @ lukewar) –