2017-01-08 83 views
0

我有一個collectionView,我剛剛添加了部分,我正在使用RealmSwift。在添加這些部分之前,我可以對數據進行更改,並在我的collectionView中查看它們的更新/刪除。領域Swift更新collectionView與節

我跟着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)的問題是,IndexPaths被硬編碼是在部分0.我的應用程序崩潰是由於這讓我周圍中搜索和跨this問題就在GitHub上,當我編輯了一個項目。 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密切相關的stackoverflow問題,其中@jpsim回答某人關於在tableView中有多個部分的問題。在評論@MikePollard詢問是否有可能通過域收集通知將tableView與多個部分組合在一起。 JPSim說這很棘手,但可能。雖然我有一個collectionView而不是一個tableView,但我假設這也是可能的。

我已經試過什麼:

  1. 因爲我需要知道的項目來自於部分,我創建了一個變量來存儲被選爲該項目的indexPath。 var indexPathForDeletion = IndexPath()

    然後我在didSelectItem中設置,並在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.deleteItems(at: [self.indexPathForDeletion]) 
         }, completion: { (completed: Bool) in 
          self.collectionView.reloadData() 
         }) 
         break 
        case let .error(error): 
         print(error.localizedDescription) 
        } 
    } 
    

    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).'

    我開始用2項的應用程序崩潰,我刪除了1個項目,我應該留1個項目,但它似乎我還有2.這是我的錯誤解釋。我解釋正確嗎?爲什麼不能刪除該項目?

  2. 我有一個散列表來存儲節和它的結果數組,所以我創建了一個函數來更新散列表,然後重新加載collectionView。

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

    這給了我一個「更好」的結果,但似乎有些不可思議。我可以刪除項目iff它們位於索引0處,而不管區段如何。但是,刪除索引爲0的項目將刪除它所在的整個部分。

我在想什麼?

回答

1

取決於您的集合視圖有多少個區段,爲每個區段的每組結果設置一個單獨的通知區塊可能更簡單。這需要爲每個部分(以及隨後的通知令牌)維護一個單獨的Results對象,因此根據您擁有多少部分,此解決方案可能有點複雜。

另一個考慮因素可能是嘗試RBQFetchedResultsController。這是在Realm發佈更改通知之前構建的控制器(作爲Realm員工的第三方項目),因此雖然它不像主集合通知系統那樣是「原生」,但它也可以用於表/集合視圖部分。

+0

謝謝@TiM!我只有十幾個部分。我現在意識到,我誤解了你的建議,但它引導了我實施的解決方案,即爲每個部分設置單獨的通知。然後我更新了我的哈希表並重新加載了collectionView。 –

+0

@MaryMartinez如何做'單獨的通知' – aelam