删除导致应用崩溃

时间:2015-06-10 14:43:25

标签: ios swift

我正在尝试整理我的第一个iOS应用程序(我主要是一个PHP开发人员),我遇到了一个问题。我试图按照教程制作一个简单的任务管理器应用程序,除了删除功能外,我还能正常工作。

当我尝试删除某个项目时,该应用程序崩溃时出现以下错误:

2015-06-10 08:33:32.532 Tasks[56594:1355112] *** Assertion failure in
-[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-3347.44/UITableView.m:1623

2015-06-10 08:33:32.538 Tasks[56594:1355112] *** Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in
section 0.  The number of rows contained in an existing section after the update (1) must
be equal to the number of rows contained in that section before the update (1), plus or
minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and
plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'

之后有一个抛出调用堆栈消息,如果需要,我也可以发布。

这是我的MasterViewController.swift文档:

//
//  MasterViewController.swift
//  Tasks
//
//  Created by John Doe on 6/9/15.
//  Copyright (c) 2015 John Doe. All rights reserved.
//

import UIKit

class MasterViewController: UITableViewController {

    var objects = [Task]()

    var count: Int {
        return objects.count
    }

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.navigationItem.leftBarButtonItem = self.editButtonItem()
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated);
        self.objects = TaskStore.sharedInstance.tasks;
        self.tableView.reloadData();
    }

    override func didReceiveMemoryWarning() {
        // Dispose of any resources that can be recreated.
        super.didReceiveMemoryWarning()
    }

    // MARK: - Segues

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "showDetail" {
            if let indexPath = self.tableView.indexPathForSelectedRow() {
                let task = TaskStore.sharedInstance.get(indexPath.row)
                (segue.destinationViewController as! DetailViewController).detailItem = task
            }
        }
    }

    // MARK: - Table View

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return objects.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell

        let task = TaskStore.sharedInstance.get(indexPath.row)
        cell.textLabel?.text = task.title
        cell.detailTextLabel?.text = task.notes
        return cell
    }

    override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // Return false if you do not want the specified item to be editable.
        return true
    }

    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == .Delete {
            TaskStore.sharedInstance.removeTaskAtIndex(indexPath.row)
            tableView.beginUpdates()
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
            tableView.endUpdates()
        } 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.
        }
    }


}

一位朋友提到我应该在删除代码之前和之后添加beginUpdates()和endUpdates()方法,但我仍然会收到相同的错误消息并崩溃。

任何建议都会非常感激,我觉得通过参考阅读并没有让我到处都是。谢谢!

3 个答案:

答案 0 :(得分:1)

它与beginUpdates()endUpdates()无关;如果您需要多个动画(在第1部分中插入x行,在第2部分中删除y行),则使用这些动画。

您的问题在于您有时使用本地变量objects,有时使用TaskStore.sharedInstance。您正在从TaskStore中删除任务,但您仍在使用objects来确定行数。

最简单的方法是完全摆脱objects,只使用TaskStore.sharedInstance。但是,在某些情况下保留本地副本是有意义的,例如如果您包含'保存'和'取消'纽扣。在这种情况下,您应该在viewDidLoad中获取对象(就像您现在一样),在其他任何地方使用objects,当用户点击“保存”时,请将更改写回商店。

答案 1 :(得分:0)

删除后同步objects数组。

self.objects = TaskStore.sharedInstance.tasks

如果您想使用objects数组作为数据源,请在任何地方使用它。或者根本不使用它,而是使用TaskStore.sharedInstance

答案 2 :(得分:0)

我猜测TaskStore.sharedInstance.tasks不是一个可变数组。当您将对象分配给TaskStore.sharedInstance.tasks,然后修改非可变数组时,您基本上创建一个新数组并丢弃旧数组(只有它不被丢弃,因为objects保持不变对它的引用),然后将新数组分配给TaskStore.sharedInstance.tasks。现在,TaskStore.sharedInstance.tasksobjects指向的数组不同。

由于表行和objects.count的计数不同,您会收到错误。

您应该考虑使用可变数组,在修改数组后更新objects,或者停止使用变量objects