删除行时TableView“无法识别的选择器发送到实例”错误

时间:2014-10-29 07:46:32

标签: ios uitableview swift

我有一个按钮可以删除它所在的单元格。数据模型工作正常,tableView.reloadData()不会导致错误。但是,当我使用tableView.deleteRowsAtIndexPaths(..)时,会发生崩溃,告诉我以下内容:

-[__NSCFNumber row]: unrecognized selector sent to instance 0xb000000000000003
2014-10-29 03:37:08.999 SampleApp[4915:82542] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber row]: unrecognized selector sent to instance 0xb000000000000003'

指示发生这种情况的代码如下所示。我觉得这与我的通知有关,但我不知道为什么。我在发布通知时尝试使用nil作为对象的参数,但这并没有什么不同。我不明白为什么tableView.reloadData()可以工作,而替代方法不会。我怎样才能阻止这种情况发生?

GoalTableViewCell类,它继承自UITableViewCell(摘录)

@IBAction func deleteButtonTapped(sender: AnyObject) { //IBAction is connected to a delete button within the cell.
        let index = self.indexInTable //indexInTable is an Int property that tracks where the cell is located in the tableView. It is updated using cellForRowAtIndexPath(..)
        var userInfo = ["index" : index]
        NSNotificationCenter.defaultCenter().postNotificationName("DeletedGoal", object: self, userInfo: userInfo)
    }
继承自UIViewController的

GoalsTableViewController类(并且其中包含一个tableView)(摘录)

    func deletedGoal(notification : NSNotification) {
        if (notification.name == "DeletedGoal") {
            var userInfo = notification.userInfo!
            var index = userInfo["index"] as Int //this is returning the proper index.

            goalsArray.removeAtIndex(index)
            saveGoals(goalsArray)
            //self.tableView.reloadData() //this works.
            self.tableView.deleteRowsAtIndexPaths([index], withRowAnimation: UITableViewRowAnimation.Fade) //this causes error

        }
    }

编辑:我更正了代码(非常感谢大家),但遇到了新的错误。我可能只是为此打开一个新问题:在连续删除更多数量的单元格后,我最终得到一个崩溃告诉我indexPath太高了。我猜测cellForRowAtIndexPath(..)是问题,它不标记单元格的indexInTable属性,除非发生滚动(?)

    //correct code
   func deletedGoal(notification : NSNotification) {
            if (notification.name == "DeletedGoal") {
                var userInfo = notification.userInfo!
                //var cell = userInfo["cell"] as GoalTableViewCell
            var index = userInfo["index"] as Int

            println(index)
            goalsArray.removeAtIndex(index)
            saveGoals(goalsArray)
            let indexPath = NSIndexPath(forRow:index,inSection:0)
            self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
            //self.tableView.reloadData()

        }
    }

2 个答案:

答案 0 :(得分:2)

如果查看异常消息,您将看到[__NSCFNumber row],它告诉您尝试在NSCFNumber上调用row方法(这是NSNumber的内部类) - 没有行方法。

现在看看self.tableView.deleteRowsAtIndexPaths([index], withRowAnimation: UITableViewRowAnimation.Fade) - 方法名称告诉您(或者您可以阅读文档)它想要一个NSIndexPath的数组而不是NSNumber s

所以,你想说的是

self.tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow:index inSection:0)], withRowAnimation:UITableViewRowAnimation.Fade)

这假设您的表只有一个部分。如果它有多个部分,那么您需要跟踪单元格和行中的部分编号。您可以通过将存储的属性更改为indexPath而不是IndexPath.row来执行此操作。

然后你可以说

@IBAction func deleteButtonTapped(sender: AnyObject) { //IBAction is connected to a delete button within the cell.
        let index = self.indexInTable //indexInTable is an NSIndexPath property that tracks where the cell is located in the tableView. It is updated using cellForRowAtIndexPath(..)
        var userInfo = ["index" : index]
        NSNotificationCenter.defaultCenter().postNotificationName("DeletedGoal", object: self, userInfo: userInfo)
    }

func deletedGoal(notification : NSNotification) {
    if (notification.name == "DeletedGoal") {
        var userInfo = notification.userInfo!
        var index = userInfo["index"] as NSIndexPath

        goalsArray.removeAtIndex(index.row)
        saveGoals(goalsArray)
        //self.tableView.reloadData() //this works.
        self.tableView.deleteRowsAtIndexPaths([index], withRowAnimation: UITableViewRowAnimation.Fade) //this causes error

    }
}

答案 1 :(得分:1)

问题很可能是var index被设置为int类型。

但是,方法deleteRowsAtIndexPaths需要一个NSIndexPath类型的对象,因为它在内部会调用传递路径上的选择器行。

在你的情况下,在Int上调用选择器,它不响应行选择器。创建一个索引路径,首先将索引作为您的行,然后您就可以了。 :D