2017-11-27 23 views
0

私はUITableViewに2つのセクションを持っています。各セクションには、特定のレルムオブジェクトのクエリ結果が表示されます。グループ化されたUITableViewとレルム通知

var contentRequests: Results<UESocketPostRequest>? { 
    return try? CustomRealm.realm().objects(UESocketPostRequest.self).filter("completed = false AND content != nil").sorted(byKeyPath: "content.createdAt", ascending: false) 
} 

var mediaUploads: Results<UEMediaUploadRequest>? { 
    return try? CustomRealm.realm().objects(UEMediaUploadRequest.self).filter("finished = false").sorted(byKeyPath: "media.content.createdAt", ascending: false) 
} 

マイUITableViewDelegateUITableViewDataSource適合:

func numberOfSections(in tableView: UITableView) -> Int { 
    return 2 
} 

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    switch section { 
    case 0: 
     return self.contentRequests?.count ?? 0 
    case 1: 
     return self.mediaUploads?.count ?? 0 
    default: 
     return 0 
    } 
} 

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "UPLOADCELL") as? UEUploadCell else { 
     return UITableViewCell() 
    } 

    switch indexPath.section { 
    case 0: 
     if let request = self.contentRequests?[indexPath.row] { 
      cell.softBindSocketRequest(request) 
     } 
    case 1: 
     if let request = self.mediaUploads?[indexPath.row] { 
      cell.softBindMediaUploadRequest(request) 
     } 
    default: 
     break 
    } 

    return cell 
} 

私はその後、私のレルム結果ごとにNotificationToken年代を設定し、このようなテーブルビューを更新します。

func startContentToken() { 
    self.contentToken = self.contentRequests?.observe({ [weak self] (changes) in 
     switch changes { 
     case .error: 
      break 
     case .initial: 
      let indexSet = IndexSet(integer: 0) 
      self?.tableView.reloadSections(indexSet, with: .automatic) 
     case .update(let content, deletions: let deletions, insertions: let insertions, modifications: let modifications): 
      self?.tableView.beginUpdates() 
      self?.tableView.insertRows(at: insertions.map({ IndexPath(row: $0, section: 0) }), 
             with: .automatic) 
      self?.tableView.deleteRows(at: deletions.map({ IndexPath(row: $0, section: 0)}), 
             with: .automatic) 
      self?.tableView.reloadRows(at: modifications.map({ IndexPath(row: $0, section: 0) }), 
             with: .automatic) 
      self?.tableView.endUpdates() 
     } 
    }) 
} 

func startMediaToken() { 
    self.mediaToken = self.mediaUploads?.observe({ [weak self] (changes) in 
     switch changes { 
     case .error: 
      break 
     case .initial: 
      let indexSet = IndexSet(integer: 1) 
      self?.tableView.reloadSections(indexSet, with: .automatic) 
     case .update(let media, deletions: let deletions, insertions: let insertions, modifications: let modifications): 
      self?.tableView.beginUpdates() 
      self?.tableView.insertRows(at: insertions.map({ IndexPath(row: $0, section: 1) }), 
             with: .automatic) 
      self?.tableView.deleteRows(at: deletions.map({ IndexPath(row: $0, section: 1)}), 
             with: .automatic) 
      self?.tableView.reloadRows(at: modifications.map({ IndexPath(row: $0, section: 1) }), 
             with: .automatic) 
      self?.tableView.endUpdates() 
     } 
    }) 
} 

私は頻繁にこのログメッセージまたは同様のものによってカプセル化されたUITableView不整合例外のためクラッシュする:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 1. The number of rows contained in an existing section after the update (4) must be equal to the number of rows contained in that section before the update (0), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).

は私が何か間違ったことをやっているか、レルムは、このようにグループ化されたUITableViewさんで使用するために設計されていませんか?

答えて

2

これは、2つの通知がまったく同時に発生しないためです。 contentTokenからの更新が終了するまでに、結果のnumberOfRowsを検証すると思います。(notification-updateが1行を削除すると、結果のtableViewに更新前より1行少ないかどうかがチェックされます)。問題は、この時間までにmediaTokenがトリガされ、numberOfRowsInSection(1)が返す内容を変更してエラーが発生することです。私はかなり長い間、まったく同じ問題を抱えていましたが、残念ながら解決策を見つけることができませんでした。

+0

洞察を得てくれてありがとうございます。回避策を見つけ出すことができるかどうか少し調べてみます。 –

+0

@JonVogelあなたは解決策を考案しましたか? – sirvon

+0

いいえ。しかし、ここで私がRealm Cocoaリポジトリに提出した問題があります:https://github.com/realm/realm-cocoa/issues/5553 –

関連する問題