2012-12-12 18 views
28

UICollectionViewのヘッダーを更新する別のスレッドで取得されるデータがあります。しかし、ヘッダーやフッターなどの補足ビューを効率的に再ロードする方法は見つかっていません。UICollectionViewのヘッダーまたはフッターを再ロードしますか?

私はcollectionView reloadSections:を呼び出すことができますが、これは不要なセクション全体をリロードします。 collectionView reloadItemsAtIndexPaths:はターゲットセル(補足ビューではない)にしか見えません。また、ヘッダそのものにsetNeedsDisplayを呼び出すことは、どちらも機能していないようです。何か不足していますか?

答えて

2

ここには2つの方法があります。

1. 最終的に利用可能なデータをバックアップするための変更可能なモデルを作成します。継承されたUICollectionReusableViewクラスでKVOを使用して変更を観察し、ヘッダービューを新しいデータで更新します。

[model addObserver:headerView 
     forKeyPath:@"path_To_Header_Data_I_care_about" 
      options:(NSKeyValueObservingOptionNew | 
        NSKeyValueObservingOptionOld) 
      context:NULL]; 

は次に

- (void)observeValueForKeyPath:(NSString *)keyPath 
         ofObject:(id)object 
         change:(NSDictionary *)change 
         context:(void *)context 

2.ビューに通知リスナを追加し、データが正常に使用可能来たときに通知をポストヘッダビューでリスナーメソッドを実装します。欠点は、これがアプリケーション全体であり、クリーンなデザインではないことです。

// place in shared header file 
#define HEADER_DATA_AVAILABLE @"Header Data Available Notification Name" 

// object can contain userData property which could hole data needed. 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(headerDataAvailable:) name:HEADER_DATA_AVAILABLE object:nil]; 

[[NSNotificationCenter defaultCenter] postNotificationName:HEADER_DATA_AVAILABLE object:nil]; 
+0

私はKVOを使用していませんでしたが、私は、データの更新のために耳を傾け、私のカスタムヘッダークラ​​スのフィールドを設定し、その上にsetNeedsDisplayと呼ばれているが、何も変わっていません。私はそれを更新する方法を設計するよりも、自分自身をリフレッシュするためのヘッダーを取得することでさらに問題を抱えています。 – akaru

+0

あなたはinvalidateLayoutを呼び出してみましたか?それはあなたのヘッダーをリフレッシュしますか? – Samuel

+0

でも動作しませんでした。 – akaru

11

私はちょうど同じ問題に走った、と私はラベルを編集するために、そのタグを使用してビューを調べることになった:

UICollectionReusableView *footer = (UICollectionReusableView*)[self.collectionView viewWithTag:999]; 
UILabel *footerLabel = (UILabel*)[footer viewWithTag:100]; 

あなたはセクション全体をリロードする必要が言ったように、細胞上のアニメーションも相殺されます。私のソリューションは理想的ではありませんが、十分に簡単です。

+0

そうすれば、ヘッダの再利用を禁止したり、メモリの問題を引き起こす恐れがあります。 – akaru

+3

@カールそれは私のためにうまく動作します。それがちょうどタグなので、なぜメモリの問題があるのか​​わからない。 –

+2

KVO – TheCodingArt

3

同じ問題が発生しました。私は@ BobVorksの答えを試してみましたが、セルだけが再利用されればうまくいきました。だから、私はこれを達成するためのよりクリーンな方法を見つけようとしましたが、performBatchUpdate(完了ブロック)の後にUICollectionView全体をリロードして、うまくいきました。 insertItemsAtIndexPathにアニメーションを取り消さずに、コレクションをリロードします。実際に私は個人的に最近の2つの答えを投票したので、私はそれが働いていると思うので、私の場合は、これはそれを行うための最もクリーンな方法です。

[self.collectionView performBatchUpdates:^{ 
    // perform indexpaths insertion 
} completion:^(BOOL finished) { 
    [self.collectionView reloadData]; 
}]; 
19

また、ここで私は現在メモリにロードされている唯一のセクションのヘッダを更新するためにやったことだ

[[_collectionView collectionViewLayout] invalidateLayout] 
+3

の横に最悪の回答があります。これは本当に受け入れられた回答になるはずです – tropicalfish

+1

完璧な答え..! –

+1

レイアウト全体がリロードされます。補足的な見解にかかわらず。 – TheCodingArt

1

を使用することができます。

  • はweakToStrong NSMapTableを追加します。ヘッダーを作成するときは、indexPathオブジェクトを使用して弱く保持されたキーとしてヘッダーを追加します。ヘッダーを再利用すると、indexPathが更新されます。
  • ヘッダーを更新する必要がある場合は、必要に応じてNSMapTableからオブジェクト/キーを列挙できるようになりました。

    @interface YourCVController() 
     @property (nonatomic, strong) NSMapTable *sectionHeaders; 
    @end 

    @implementation YourCVContoller 

    - (void)viewDidLoad { 
     [super viewDidLoad]; 
     // This will weakly hold on to the KEYS and strongly hold on to the OBJECTS 
     // keys == HeaderView, object == indexPath 
     self.sectionHeaders = [NSMapTable weakToStrongObjectsMapTable]; 
    } 

    // Creating a Header. Shove it into our map so we can update on the fly 
    - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath 
    { 
     PresentationSectionHeader *header = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"presentationHeader" forIndexPath:indexPath]; 
     // Shove data into header here 
     ... 
     // Use header as our weak key. If it goes away we don't care about it 
     // Set indexPath as object so we can easily find our indexPath if we need it 
     [self.sectionHeaders setObject:indexPath forKey:header]; 
     return header; 
    } 

    // Update Received, need to update our headers 
    - (void) updateHeaders { 
     NSEnumerator *enumerator = self.sectionHeaders.keyEnumerator; 
     PresentationSectionHeader *header = nil; 
     while ((header = enumerator.nextObject)) { 
      // Update the header as needed here 
      NSIndexPath *indexPath = [self.sectionHeaders objectForKey:header]; 
     } 
    } 

    @end 
1

削除通常...この質問は非常に古いですが、それを行うための簡単な方法は、ちょうどあなたがビューを更新しながら、あなたのビューは、アニメーションをアニメーション化と無効化される時間をカバー遅延を設定することですまたは挿入が必要です。その35秒だけ実行します。

delay(0.35){ 
      UIView.performWithoutAnimation{ 
      self.collectionView.reloadSections(NSIndexSet(index: 1)) 
      } 
0
[UIView performWithoutAnimation:^{ 
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:4]]; 
}]; 

[UIView performWithoutAnimation:^{ 
[self.collectionView reloadData]; 
}]; 
関連する問題