使用Realm

时间:2015-12-28 17:47:37

标签: swift uitableview realm uisearchcontroller

我使用Realm作为我的后端数据存储,我有一个带有UISearchResults控制器的tableview。 如果我没有过滤结果,我没有问题从tableView中删除一行并将其从我的Realm数据库中删除。 但是,当我使用SearchController进行过滤并尝试滑动删除行时,我收到错误。

  

原因:'无效更新:第0部分中的行数无效   更新后现有部分中包含的行数(2)   必须等于之前该部分中包含的行数   更新(2),加上或减去插入或删除的行数   从该部分(0插入,1删除)和加号或减号   移入或移出该部分的行(0移入,0移出)。'

这是我在过滤我的位置时使用的功能

func filterContentForSearchText(searchText: String, scope: String = "All") {
        filteredLocations  = locations.filter { location in
            return location.site.lowercaseString.containsString(searchText.lowercaseString)
        }
        tableView.reloadData()
    }

这是我的tableView删除功能

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == UITableViewCellEditingStyle.Delete {
            if searchController.active && searchController.searchBar.text != "" {
                // This is from a filtered list
                do {
                    try realm.write() {
                        self.realm.delete(filteredLocations[indexPath.row])
                    }
                   tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)

                } catch {
                    print("Could not delete site")
                }
            } else {
                do {
                    try realm.write() {
                        self.realm.delete(locations[indexPath.row])
                    }
                    tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
                } catch {
                    print("Could not delete site")
                }
            }
        }
    }

有人可以帮我解决这个问题吗?

3 个答案:

答案 0 :(得分:1)

我在这个问题上挣扎了很长时间。自问这个问题以来已经有一段时间了,但对于未来的人们来说,这可能会有所帮助。我不知道Realm,但对于那些使用Core Data的人,我发现我需要做的就是在fetchedResultsController didChangeObject方法中重新加载tableview以进行删除和更新。

例如:

func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
    switch type {
        case .Insert:
            tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
        case .Delete:

            if searchController.active && searchController.searchBar.text != "" {
                tableView.reloadData()//THIS
            } else {
                tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
            }//if else

        case .Update:

            if searchController.active && searchController.searchBar.text != "" {
                tableView.reloadData()//AND THIS
            } else {
                self.configureCell(tableView.cellForRowAtIndexPath(indexPath!)!, atIndexPath: indexPath!)
            }//if else

        case .Move:
            tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
            tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
    }
}//controller:didChangeObject

答案 1 :(得分:0)

如果您尝试删除单元格而不首先从数据源中完全删除等效对象,则会在UITableView中出现该错误消息。错误消息显示section after the update (2)而不是(1)的事实似乎暗示您的数据源仍然悬挂在您刚从Realm删除的项目的引用上。

从它的外观来看,既然你是自己手动生成filteredObjects的内容,你可能需要在从Realm删除它之后手动删除它的条目,但是在调用UITableView单元格删除方法之前。

if searchController.active && searchController.searchBar.text != "" {
    // This is from a filtered list
    do {
        try realm.write() {
            self.realm.delete(filteredLocations[indexPath.row])
        }
        filteredLocations.removeAtIndex(indexPath.row)
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
    } catch {
        print("Could not delete site")
    }
}

我猜它正常工作正常,因为locations很可能是来自Realm的Results对象,它会在您指示Realm删除它后自动更新自己以删除该项目。 / p>

答案 2 :(得分:0)

我有同样的问题,问题实际上与Realm对象删除无关。它与删除对象后的tableview行数不同有关。我能够对搜索控制器进行if检查,并确定是否需要运行.deleteRowsAtIndexPaths。这解决了我的崩溃,但搜索结果不会更新以反映删除的对象。它只会挂起。对.searchResultsUpdater的调用修复了这个问题。不确定它是否会有所帮助,但我的应用程序中的代码如下。请注意我使用辅助类来执行所有Realm函数,并在删除行后重新加载数据源数组。

    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == .Delete {

        var studentToDelete = Student()

        if searchController.active && searchController.searchBar.text != ""{
            studentToDelete = filteredStudents[indexPath.row]
            DBhelper.deleteByName(studentToDelete.name)
            students = DBhelper.getAllObjetcs()
            searchController.searchResultsUpdater?.updateSearchResultsForSearchController(searchController)

        }else{
            studentToDelete = students[indexPath.row]
            DBhelper.deleteByName(studentToDelete.name)
            students = DBhelper.getAllObjetcs()
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        }


    } else if editingStyle == .Insert {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }
}