2017-01-08 12 views
0

私はセクションを追加したばかりのコレクションビューを持っており、RealmSwiftを使用しています。セクションを追加する前に、データを変更して、コレクションビューでデータを更新/削除することができました。レルムセクションを含むコレクションビューを更新中

私はdocsに続いて、結果オブジェクトの変更によってUIの変更がトリガーされるように通知を追加しました。通知私は自分のcollectionViewに適切な変更を加えました。

func notificationSubscription(for outfits: Results<Outfit>) -> NotificationToken { 
    return outfits.addNotificationBlock({ [weak self] (changes: RealmCollectionChange<Results<Outfit>>) in 
     self?.updateUI(with: changes) 
    }) 
} 

func updateUI(with changes: RealmCollectionChange<Results<Outfit>>) { 
    switch changes { 
    case .initial(_): 
     collectionView.reloadData() 
    case let .update(_, deletions, insertions, modifications): 
     collectionView.performBatchUpdates({ 
      self.collectionView.reloadItems(at: modifications.map { IndexPath(row: $0, section: 0) }) 
      self.collectionView.insertItems(at: insertions.map { IndexPath(row: $0, section: 0) }) 
      self.collectionView.deleteItems(at: deletions.map { IndexPath(row: $0, section: 0) }) 
     }, completion: { (completed: Bool) in 
      self.collectionView.reloadData() 
     }) 
     break 
    case let .error(error): 
     print(error.localizedDescription) 
    } 
} 

それはupdateUI(with: changes)における問題は、私は周りに検索し、GitHubの上this問題に出くわしたので、私はアイテムを編集したときIndexPathsが原因これにセクション0で私のアプリがクラッシュしたようにハードコードされていることであることを私には明らかです。 Pawelkata(コメント者)は、問題の迅速な修正(現在閉鎖)は、switch文のupdateの中からcollectionView.reloadData()を呼び出すことであると述べました。

func updateUI(with changes: RealmCollectionChange<Results<Outfit>>) { 
    switch changes { 
    case .initial(_): 
     collectionView.reloadData() 
    case let .update(_, deletions, insertions, modifications): 
     collectionView.reloadData() 
     break 
    case let .error(error): 
     print(error.localizedDescription) 
    } 
} 

クイックフィックスは、修正や挿入のために機能しますが、削除の場合は失敗します。これは、新しいデータが他の場所で追加/変更されているためですが、同じviewControllerで削除が行われるため、変更によって実際にUIが更新されるわけではありません。

私が見つけたのはthis @jpsimはtableViewに複数のセクションを持つことに関する誰かの質問に答えています。コメントで@MikePollardは、複数のセクションでtableViewをレルムコレクションの通知と組み合わせることができるかどうかを尋ねます。 JPSimはそれが難しいと言いますが、可能です。私はcollectionViewを持っていますが、テーブルビューではありませんが、これも可能であるという前提を作っています。

は、私が試した何を:私はアイテムがどこから来たのセクションを知るために必要なので

  1. 、私が選択した項目のindexPathを格納する変数を作成しました。 var indexPathForDeletion = IndexPath()

    これをdidSelectItemに設定し、updateUI(with: changes)で使用します。私は2つの項目で開始Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of items in section 2. The number of items contained in an existing section after the update (2) must be equal to the number of items contained in that section before the update (2), plus or minus the number of items inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).'

    func updateUI(with changes: RealmCollectionChange<Results<Outfit>>) { 
        switch changes { 
        case .initial(_): 
         collectionView.reloadData() 
        case let .update(_, deletions, insertions, modifications): 
         collectionView.performBatchUpdates({ 
          self.collectionView.deleteItems(at: [self.indexPathForDeletion]) 
         }, completion: { (completed: Bool) in 
          self.collectionView.reloadData() 
         }) 
         break 
        case let .error(error): 
         print(error.localizedDescription) 
        } 
    } 
    

    アプリのクラッシュは、私は1つのアイテムを削除し、私は1つの項目が残っているはずですが、私はまだエラーの私の解釈だ2を持って表示されます。私はそれを正しく解釈しましたか?なぜアイテムは削除されませんでしたか?

  2. セクションを格納するハッシュテーブルがあり、結果の配列なので、ハッシュテーブルを更新してからコレクションビューを再ロードする関数を作成しました。

    func refreshData() { 
        getOutfitsByCategory() 
        collectionView.reloadData() 
    } 
    
    func getOutfitsByCategory() { 
        for category in categories { 
         outfitsByCategory[category] = outfits.filter("category = %@", category) 
        } 
    } 
    

    これは私に「良い」結果を与えますが、奇妙なことがいくつかあります。私は項目に関係なく、のインデックス0にあるアイテムを削除することができます。ただし、インデックス0のアイテムを削除すると、そのセクション全体が削除されます。

何が欠けていますか?

答えて

1

コレクションビューのセクション数に応じて、各セクションの結果セットごとに別々の通知ブロックを設定するほうが簡単です。これにより、各セクション(および後続の通知トークン)に個別のResultsオブジェクトを保持する必要があります。したがって、セクション数に応じて、このソリューションはやや複雑になる可能性があります。

もう1つの考慮点は、RBQFetchedResultsControllerを試してみることです。これは、レルムの変更通知がRealm従業員によってサードパーティのプロジェクトとして利用可能になる前に構築されたコントローラであるため、メインコレクション通知システムと同じではありませんが、テーブル/コレクションビューセクションも考慮することができます。

+0

ありがとう@TiM!私には約12のセクションしかありません。私はあなたの提案を誤解してしまったと認識しましたが、実装したソリューションに私を導いてくれました。これはセクションごとに別々の通知を設定することでした。私はちょうど私のハッシュテーブルを更新し、コレクションビューを再ロードしました。 –

+0

@MaryMartinez「別々の通知」を行う方法 – aelam

関連する問題