' NSInternalInconsistencyException',原因:'尝试将第4行插入第0部分,但更新后第0部分只有4行'

时间:2016-06-19 17:33:57

标签: ios arrays swift uitableview dictionary

好的,我已经在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中实现了一个协议,以便将数据发送回过去的视图控制器,所以我做了一个我最近也学到的委托。继承人加上我的意见:

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

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

2 个答案:

答案 0 :(得分:0)

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

为键分配数组&#34; 0&#34;变量check并附加值

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

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

name[0] = check

使用密钥的实际字母而不是不相关的数字是否更方便?

答案 1 :(得分:0)

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