2012-12-24 62 views

回答

44
// In viewDidLoad 
[self.collectionView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld context:NULL]; 

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    // You will get here when the reloadData finished 
} 

- (void)dealloc 
{ 
    [self.collectionView removeObserver:self forKeyPath:@"contentSize" context:NULL]; 
} 
+0

這崩潰爲我當我回導航,否則效果不錯 – ericosg

+2

@ericosg add'[self.collectionView removeObserver:self forKeyPath:@」contentSize「 context:NULL];'to'-viewWillDis出現:動畫:'以及。 – pxpgraphics

+0

太棒了!非常感謝你! – Abdo

-6

你可以這樣做......

- (void)reloadMyCollectionView{ 

     [myCollectionView reload]; 
     [self performSelector:@selector(myStuff) withObject:nil afterDelay:0.0]; 

    } 

    - (void)myStuff{ 
    // Do your stuff here. This will method will get called once your collection view get loaded. 

    } 
+0

儘管這段代碼可以回答這個問題,提供 關於_why_和/或_how_它回答 問題將顯著改善其長期 值附加的上下文。請[編輯]你的答案,添加一些解釋。 –

-7

試試這個:

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 
{ 
    return _Items.count; 
} 

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UICollectionViewCell *cell; 
    //Some cell stuff here... 

    if(indexPath.row == _Items.count-1){ 
     //THIS IS THE LAST CELL, SO TABLE IS LOADED! DO STUFF! 
    } 

    return cell; 
} 
+2

這是不正確的,cellFor會被調用,只有該單元格將是可見的,在這種情況下,最後一個可見項目將不會等於項目的總數量... – Jirune

23

這其實相當簡單。

當例如調用UICollectionView的reloadData方法或它的佈局的的invalidateLayout方法,你做到以下幾點:

dispatch_async(dispatch_get_main_queue(), ^{ 
    [self.collectionView reloadData]; 
}); 

dispatch_async(dispatch_get_main_queue(), ^{ 
    //your stuff happens here 
    //after the reloadData/invalidateLayout finishes executing 
}); 

爲什麼這個工程:

主線程(這是我們應該做所有的UI更新)包含主隊列,這是串行的,即它以FIFO方式工作。所以在上面的例子中,第一個塊被調用,它調用了我們的reloadData方法,接着是第二個塊中的其他任何東西。

現在主線程也被阻塞了。所以如果你是reloadData需要3秒執行,那麼第二個塊的處理將被那些3秒推遲。

+2

我其實只是測試了這個,在我所有的其他委託方法之前調用該塊。所以它不起作用? – taylorcressy

+0

@taylorcressy嘿,我已經更新了代碼,現在我在2個生產應用程序中使用了這些代碼。還包括解釋。 – dezinezync

+0

不適用於我。當我調用reloadData時,collectionView在執行第二個塊之後請求單元格。所以我有@taylorcressy似乎有同樣的問題。 – Raphael

71

這爲我工作:

[self.collectionView reloadData]; 
[self.collectionView performBatchUpdates:^{} 
           completion:^(BOOL finished) { 
            /// collection-view finished reload 
           }]; 
+0

謝謝。這對我有用! – Tander

+1

我試過了,但在我的情況下沒有奏效。 –

+0

無法在iOS9中工作(在iOS8上工作) – RolandasR

1

這個工作對我來說:

__weak typeof(self) wself= self; 
[self.contentCollectionView performBatchUpdates:^{ 
    [wself.contentCollectionView reloadData]; 
} completion:^(BOOL finished) { 
    [wself pageViewCurrentIndexDidChanged:self.contentCollectionView]; 
}]; 
+2

廢話......這還沒有完成任何方式佈局。 – Magoo

4

做這樣的:

 UIView.animateWithDuration(0.0, animations: { [weak self] in 
       guard let strongSelf = self else { return } 

       strongSelf.collectionView.reloadData() 

      }, completion: { [weak self] (finished) in 
       guard let strongSelf = self else { return } 

       // Do whatever is needed, reload is finished here 
       // e.g. scrollToItemAtIndexPath 
       let newIndexPath = NSIndexPath(forItem: 1, inSection: 0) 
       strongSelf.collectionView.scrollToItemAtIndexPath(newIndexPath, atScrollPosition: UICollectionViewScrollPosition.Left, animated: false) 
     }) 
0

這是我如何解決問題Swift 3.0:

override func viewDidAppear(_ animated: Bool) { 
    super.viewDidAppear(animated) 

    if !self.collectionView.visibleCells.isEmpty { 
     // stuff 
    } 
} 
+0

這不起作用。一旦第一個單元格被加載,VisibleCells就會有內容...問題是我們想知道何時加載最後一個單元格。 –

6

我想補充一個偉大@dezinezync答案:

斯威夫特3+

collectionView.collectionViewLayout.invalidateLayout() // or reloadData() 
DispatchQueue.main.async { 
    // your stuff here executing after collectionView has been layouted 
} 
+0

@nikas我們必須添加在視圖中確實出現! – SARATH

+1

不一定,您可以在佈局最終加載時從任何地方調用它。 – nikans

0

防守做到這一點:

//Subclass UICollectionView 
class MyCollectionView: UICollectionView { 

    //Store a completion block as a property 
    var completion: (() -> Void)? 

    //Make a custom funciton to reload data with a completion handle 
    func reloadData(completion: @escaping() -> Void) { 
     //Set the completion handle to the stored property 
     self.completion = completion 
     //Call super 
     super.reloadData() 
    } 

    //Override layoutSubviews 
    override func layoutSubviews() { 
     //Call super 
     super.layoutSubviews() 
     //Call the completion 
     self.completion?() 
     //Set the completion to nil so it is reset and doesn't keep gettign called 
     self.completion = nil 
    } 

} 

然後調用你這樣的VC

let collection = MyCollectionView() 

self.collection.reloadData(completion: { 

}) 

確保您使用的是子類!

相關問題