【问题标题】:'NSInternalInconsistencyException', reason: 'attempt to insert row 4 into section 0, but there are only 4 rows in section 0 after the update''NSInternalInconsistencyException',原因:'尝试将第 4 行插入第 0 节,但更新后第 0 节只有 4 行'
【发布时间】:2016-06-19 17:33:56
【问题描述】:

好的,我已经在 obj C 中看到过以前的问题并尝试过。我正在尝试构建的是一个类似于 iphone 的联系人应用程序。我在表中插入行时遇到了这个问题。早些时候,在插入行时我从来没有遇到过这个问题,我可能认为这是因为我的数据结构不好?

我尝试的解决方案是 tableView.beginUpdates 和 endUpdates 但仍然是同样的错误。这是我的联系人列表代码。

    class ContactsListViewController:  UITableViewController, AddContactViewControllerDelegate {

    let cellID = "contactCellID"
    var sectionNames = ["A","B","C","D"]
    var name = [0: ["Amber", "Ajay", "Abhishek", "Anshul"], 1: ["Borat", "Bruno", "Billooo"], 2: ["Chinku","Champu","Champak"], 3: ["Daya", "Divya","Delhi Police"]]

//    
//    @IBOutlet weak var addBarOutlet: UIBarButtonItem!
//    @IBAction func addBarButton(sender: UIBarButtonItem) {
//        performSegueWithIdentifier("AddItemSegueID", sender: addBarOutlet)
//    }
//   

    //var nameSet = ["0": "Amber", "1": "Blah", "2": "Chris" ]
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return name.count
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        let array = name[section]
        return (array!.count)
    }
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier(cellID, forIndexPath: indexPath)
        let nameArray = name[indexPath.section]
//        guard let nameArray = name[indexPath.section] else {
//            print("Invalid ")
//            cell.textLabel?.text = "Not Found"
//            return cell
//        }

        cell.textLabel?.text = nameArray![indexPath.row]
        return cell
    }
    override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        var Keys = [Int] (name.keys)
        Keys.sortInPlace()
        let value = Keys[section]
        var sec = ""
        if value == Keys[section] {
            sec = sectionNames[section]
        }
        return sec

    }
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        tableView.deselectRowAtIndexPath(indexPath, animated: true)
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "AddItemSegueID" {
           // let navcontroller = segue.destinationViewController as! UINavigationController
           // let controller = navcontroller.topViewController as! AddContactViewController
            let controller = segue.destinationViewController as! AddContactViewController
            controller.delegate = self
        }
    }

    func addContactViewController(controller: AddContactViewController, didFinishAdding item: ContactNames) {

        //var dictKeys = [Int](name.keys)
        let newName = item.text
        let firstIndex = newName.startIndex
        //let firstChar = newName[firstIndex]
        var check = name[0]!

        let newRowIndex = check.count

        check.append(newName)
        tableView.beginUpdates()
        let indexPath = NSIndexPath(forRow: newRowIndex, inSection: 0)
        let indexPaths = [indexPath]
        tableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: .Automatic)
        tableView.endUpdates()

        dismissViewControllerAnimated(true, completion: nil)
    }
    func addContactViewControllerDidCancel(controller: AddContactViewController) {
        dismissViewControllerAnimated(true, completion: nil)
    }
}


ContactNames 是包含字符串属性的普通 swift 类。 另一件事是我在 AddItemVC 中实现了一个协议,以便将数据发送回之前的视图控制器,所以我创建了一个我最近也学到的委托。这是你addItemVC:

 protocol AddContactViewControllerDelegate: class {

    func addContactViewControllerDidCancel(controller: AddContactViewController)
    func addContactViewController(controller: AddContactViewController, didFinishAdding item: ContactNames)
}

class AddContactViewController: UIViewController, UITextFieldDelegate {


    weak var delegate: AddContactViewControllerDelegate?

    @IBOutlet weak var nameField: UITextField!

    @IBOutlet weak var doneOutlet: UIBarButtonItem!

    var contactList = ContactsListViewController()
    override func viewDidLoad() {
        nameField.becomeFirstResponder()
        self.tabBarController?.tabBar.hidden = true
        doneOutlet.enabled = false
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        nameField.resignFirstResponder()

    }
    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        let oldText: NSString = textField.text!
        let newText: NSString = oldText.stringByReplacingCharactersInRange(range, withString: string)
        doneOutlet.enabled = (newText.length>0)
//        if newText.length > 0 {
//            doneOutlet.enabled = true
//        }else {
//            doneOutlet.enabled = false
//        }

        return true
    }

    @IBAction func saveAction(sender: UIBarButtonItem) {
        let newItem = ContactNames()
        newItem.text = nameField.text!

        delegate?.addContactViewController(self, didFinishAdding: newItem)

    }
    @IBAction func cancelAction(sender: UIBarButtonItem) {
        delegate?.addContactViewControllerDidCancel(self)
    }
}

如果您为此建议更好的数据结构。

【问题讨论】:

  • 我的解决方案:'controller.navigationController?.popViewControllerAnimated(true)' 替换为dismissviewcontroller

标签: ios arrays swift uitableview dictionary


【解决方案1】:

Swift 中的原生集合类型是值类型,这意味着当您为键或索引获取值时,始终会复制对象。

您将键“0”的数组分配给变量check 并附加一个值

var check = name[0]!
...
check.append(newName)

但这确实不会更改字典name 中的原始数组。 您需要将数组分配回字典

name[0] = check

用实际的字母代替不相关的数字不是更方便吗?

【讨论】:

  • 找到它:试过也没有工作同样的错误。在调试期间dismissviewcontroller没有接到电话不知道尝试过controller.dismiss ...。解决方案是 navigationController.popViewControllerAnimated(true)。谢谢你:)
【解决方案2】:

在 beginUpdates 和 endUpdates 之间,您需要更新数据源,使其与 insertRowsAtIndexPaths 等操作相匹配。因此,如果您有四行,并且像您一样插入一,您的数据源也必须更改为现在有五行。正如错误消息所说。

【讨论】:

  • 其实begin/endUpdates在这种情况下完全没有作用(单次插入动作),可以省略。仅在调用insertRowsAt... 之前 必须更新数据源数组
  • 好的,那我该如何更新数据源呢?你是说我的字典吗?我发现这个方法用于更新字典。 'updateValue(forKey:)' 但即使这样我怎么能动态地做到这一点?我想出了这个更多的方法'tableView.reloadData()',它给出了同样的错误
猜你喜欢
  • 2017-12-10
  • 1970-01-01
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多