Удаление объекта после редактирования свойства в области приводит к возникновению причины RLMException: "Индекс 0 выходит за пределы (должен быть меньше 0)"

Я делаю простое приложение, где пользователь может добавить привычки и закончить тему, используя Swift и Realm для базы данных

Все работает нормально, кроме случаев, когда я редактирую состояние и удаляю объект. Приложение вылетает по причине RLMException: "Индекс 0 выходит за пределы (должен быть меньше 0)"

Я заметил, что это происходит только тогда, когда элемент является единственной ячейкой в ​​tableView

Я был бы признателен, если бы кто-нибудь мог мне помочь с этим, так как я боролся с этим весь день.

Привычный объект:

class Habit: Object {

 dynamic var id = 0
 dynamic var name = ""
 dynamic var state = ""

 convenience init(name: String) {
    self.init()
    self.id = self.incrementaID()
    self.name = name
    self.state = "in Progress"
 }

 override class func primaryKey() -> String? {
    return "id"
 }

 private func incrementaID() -> Int {
    let realm = try! Realm()
    let value = realm.objects(Habit).map{$0.id}.maxElement() ?? 0
    return value + 1
 }}

Я использую RealmSwift, https://cocoapods.org/pods/SwiftFetchedResultsController для автоматического обновления tableView, swift 2 и Xcode 7

Вот соответствующий код TableViewController в MyHabitsViewController

    override func viewDidLoad() {
    super.viewDidLoad()

    // Get the default Realm
    realm = try! Realm()

    let predicate = NSPredicate(value: true)
    let fetchRequest = FetchRequest<Habit>(realm: realm, predicate: predicate)
    let sortDescriptor = SortDescriptor(property: "name", ascending: true)
    let sortDescriptorSection = SortDescriptor(property: "state", ascending: false)

    fetchRequest.sortDescriptors = [sortDescriptorSection, sortDescriptor]

    self.fetchedResultsController = FetchedResultsController<Habit>(fetchRequest: fetchRequest, sectionNameKeyPath: "state", cacheName: nil)
    self.fetchedResultsController!.delegate = self
    self.fetchedResultsController!.performFetch()
}

Методы FetchedResultsControllerDelegate:

func controllerWillChangeContent<T : Object>(controller: FetchedResultsController<T>) {
    tableView.beginUpdates()
}

func controllerDidChangeSection<T : Object>(controller: FetchedResultsController<T>, section: FetchResultsSectionInfo<T>, sectionIndex: UInt, changeType: NSFetchedResultsChangeType) {

    let indexSet = NSIndexSet(index: Int(sectionIndex))

    switch changeType {

    case .Insert:
        tableView.insertSections(indexSet, withRowAnimation: .Fade)

    case .Delete:
        tableView.deleteSections(indexSet, withRowAnimation: .Fade)

    case .Update:
        tableView.reloadSections(indexSet, withRowAnimation: .Fade)

    case .Move:
        tableView.deleteSections(indexSet, withRowAnimation: .Fade)
        tableView.insertSections(indexSet, withRowAnimation: .Fade)
    }
}

func controllerDidChangeObject<T : Object>(controller: FetchedResultsController<T>, anObject: SafeObject<T>, indexPath: NSIndexPath?, changeType: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {

    switch changeType {

    case .Insert:
        tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)

    case .Delete:
        tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)

    case .Update:
        tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)

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

func controllerDidChangeContent<T : Object>(controller: FetchedResultsController<T>) {
    tableView.endUpdates()
}

UITableViewDelegate & UITableViewDataSource

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return self.fetchedResultsController!.numberOfSections()
}

func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return fetchedResultsController!.titleForHeaderInSection(section)
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.fetchedResultsController!.numberOfRowsForSectionIndex(section)
}


func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("HabitInfoCell", forIndexPath: indexPath) as! HabitInfoCell

    let habit = self.fetchedResultsController!.objectAtIndexPath(indexPath)!

    cell.configure(habit)

    // add delete button
    let deleteButton = MGSwipeButton() {

        try! self.realm.write {
            self.realm.delete(habit)
        }
    }
    cell.leftButtons = [deleteButton]

    // add complete button
    let completeButton = MGSwipeButton() {

        try! self.realm.write {
            habit.state = "Completed"
        }
    }
    cell.rightButtons = [completeButton]

    return cell
}

1 ответ

Эта ошибка отображается, когда вы передаете индекс, превышающий общее число, присутствующее в Realm Object.

  1. Проверьте, содержит ли ваша БД Realm ту запись, которую вы отображаете в Таблице.
  2. Загрузить Realm Browser на Mac: ссылка

У меня была та же проблема, я заметил, что запись не была сделана в Realm DB.

Думая, что у Царства уже есть запись, я попытался получить. Таким образом, в результате

RLMException reason: 'Index 0 is out of bounds (must be less than 0)'

  1. Войдите в Home Directory на консоли, чтобы получить файл realm.db, используя этот код:

    let path = NSHomeDirectory (). appending ("/ Documents /") print (путь)

Другие вопросы по тегам