Skip to main content
 首页 » 操作系统

ios之删除行时TableView "unrecognized selector sent to instance"错误

2024年01月01日52zhujiabin

我有一个按钮可以删除它所在的单元格。数据模型工作正常,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 作为 object 的参数,但这没有什么区别。我不明白为什么 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) 
    } 

GoalsTableViewController 继承自 UIViewController 的类(其中有一个 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() 
 
        } 
    } 

请您参考如下方法:

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

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

所以,你想说的是

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 
 
    } 
}