UICollection代理方法didDeselectItemAtIndexPath不調用的問題

需求:

  • 點擊一個cell, 會調用didSelectItemAtIndexPath:方法,而後點擊另一個cell,首先會調用didDeselectItemAtIndexPath:這個方法,而後在調用didSelectItemAtIndexPath:方法

問題:

  • 固然實現這個需求很是容易,可是當你在didSelectItemAtIndexPath中調用reloadItemsAtIndexPaths或者reloadData這兩個方法(常常在這個方法中咱們用來修改模型數據,並使用這兩個方法來刷新cell上面的顯示),來刷新cell上面的數據的時候,就會發現,didDeselectItemAtIndexPath這個方法不會調用了.

緣由

  • 我稍微分析了下緣由.在調用reloadItemsAtIndexPaths或者reloadData,系統內部是會調用數據源方法cellForItemAtIndexPath:, 而在這個方法裏面,cell的selected屬性又從新被初始化爲NO了,因此此時cell的是處於非選中狀態的,天然就不會調用didDeselectItemAtIndexPath:這個方法來取消選中.

解決方法分析

  • 找到了緣由,那麼咱們開始想辦法.
  • 咱們也許能夠在cellForItemAtIndexPath:這個方法中手動來設置cell的狀態(這裏設置cell的狀態就是cell的最終狀態,由於這個方法最後調用的).咱們立刻就能夠想到有2個方法也許能夠修改cell的selected屬性php

    • 第一種: cell的selected屬性: 讓咱們看看官方的解釋app

       
      1. This property manages the selection state of the cell only. The default value of this property is NO, which indicates that the cell is not selected.
      2. You typically do not set the value of this property directly. Changing the value of this property programmatically does not change the appearance of the cell. The preferred way to select the cell and highlight it is to use the selection methods of the collection view object.
      3. 這個屬性僅僅是用於管理cell的選中狀態.默認這個值爲NO.意味着cell默認狀況下是沒有被選中的.
      4. 一般狀況下,不要直接設置這個屬性.使用代碼來改變這個值並不會改變cell的外觀.選中cell,並讓cell顯示高亮狀態最好的方法就是調用UICollectionView相關selection方法來實現.
    • 官方也建議咱們不要直接來設置,直接設置的話有可能並不會達到你想要的效果.通過個人測試,直接設置確實沒有做用.同窗們能夠本身去試一下
    • 第二種: -[UICollectionView selectItemAtIndexPath:animated:scrollPosition:]
    • 這個方法可能就是蘋果官方建議的經過UICollectionView的對象方法來設置cell的選中狀態.測試

      • 仍是讓咱們看看官方的解釋this

         
        1. If the allowsSelection property is NO, calling this method has no effect. If there is an existing selection with a different index path and the allowsMultipleSelection property is NO, calling this method replaces the previous selection.
        2. This method does not cause any selection-related delegate methods to be called.
        3. 若是allowsSelection屬性爲NO, 調用這個方法沒有任何效果.
        4. 若是有任何另一個已經被選中cell(官方的說明是另一個索引, 同一個意思)而且allowsMultipleSelection(容許多項選擇)這個屬性爲NO, 那麼調用這個方法會取代那個cell的選中狀態.
        5. 也就是說當 allowsSelection = YES (默認就是YES), allowsMultipleSelection = NO(這個也是默認設置), 調用這個方法就會取消上一個cell的選中狀態,而後讓當前的cell選中.
    • 看完官方的解釋,相信你們都明白了,恰好就是咱們須要的屬性spa

最終解決方案

  • 綜上所述, 若是你在didSelectItemAtIndexPath:didDeselectItemAtIndexPath這兩個方法中調用了reloadItemsAtIndexPaths或者reloadData這兩個方法來刷新cell上面顯示的數據,可是發現,didDeselectItemAtIndexPath這個代理方法並無調用,你只須要作出以下的配置便可代理

     
    1. // 這兩個屬性都是默認配置的,若是你沒有修改的話,就不用寫
    2. allowsSelection = YES;
    3. allowsMultipleSelection = NO;
    4.  
    5. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    6. {
    7. // 須要配置的代碼
    8. [collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
    9. }

 

原文:http://bbs.520it.com/forum.php?mod=viewthread&tid=2549code

相關文章
相關標籤/搜索