iOS中的核心数据,索引超出范围

iOS中的核心数据,索引超出范围,ios,swift,core-data,Ios,Swift,Core Data,在我的应用程序中,我使用的是核心数据,到目前为止,一切都很好。我尝试更新条目时遇到问题。有趣的是,我可以更新实体中除地址字段之外的所有内容。我没有做任何不同的事情,但当我尝试只更新该字段时,应用程序崩溃,出现致命错误:索引超出范围。这是实际实体的屏幕截图 它只是一些客户端信息,所有条目都是字符串。在我的编辑vc中,我使用了一个var来保存客户机信息、设置委托和使用一些谓词。代码如下: //This is declared right under the class var myClientTo

在我的应用程序中,我使用的是核心数据,到目前为止,一切都很好。我尝试更新条目时遇到问题。有趣的是,我可以更新实体中除地址字段之外的所有内容。我没有做任何不同的事情,但当我尝试只更新该字段时,应用程序崩溃,出现致命错误:索引超出范围。这是实际实体的屏幕截图

它只是一些客户端信息,所有条目都是字符串。在我的编辑vc中,我使用了一个var来保存客户机信息、设置委托和使用一些谓词。代码如下:

//This is declared right under the class
var myClientToEdit: NSManagedObject = NSManagedObject()

//my save button action
@IBAction func saveMyEdits(_ sender: Any)
{
    //get the delegate
    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else
    {
        return
    }

    //get managedContext
    let managedContext = appDelegate.persistentContainer.viewContext

    //get the client's entry
    let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Clients")

    fetchRequest.returnsObjectsAsFaults = false

    //use predicates to make sure it is the client I need
    fetchRequest.predicate = NSPredicate(format: "lastName == %@", mylastName)
    fetchRequest.predicate = NSPredicate(format: "firstName == %@", myfirstName)
    fetchRequest.predicate = NSPredicate(format: "address = %@", myaddress)

    do {
        var myClientToEdit = try managedContext.fetch(fetchRequest)
        let myObject = myClientToEdit[0]

        //my correct client is printed
        print(myObject)

        //using new entries to set new values
        myObject.setValue(lastName.text!, forKey: "lastName")
        myObject.setValue(firstName.text!, forKey: "firstName")
        myObject.setValue(address.text!, forKey: "address")
        myObject.setValue(city.text!, forKey: "city")
        myObject.setValue(state.text!, forKey: "state")
        myObject.setValue(zip.text!, forKey: "zipCode")
        myObject.setValue(phoneDay.text!, forKey: "phoneDay")
        myObject.setValue(phoneEve.text!, forKey: "phoneEvening")
        myObject.setValue(email.text!, forKey: "email")

        do{
            //save
            try managedContext.save()
        }catch let error as NSError{
            print(error)
        }

    }catch let error as NSError {
        print(error)
    }

   //dismis upon saving edits 
    self.dismiss(animated: true, completion: nil)
}
//这是在类下面声明的
var myClientToEdit:NSManagedObject=NSManagedObject()
//我的保存按钮操作
@iAction func saveMyEdits(\发送方:任意)
{
//抓住代表
让appDelegate=UIApplication.shared.delegate作为?appDelegate else
{
返回
}
//获取managedContext
让managedContext=appDelegate.persistentContainer.viewContext
//获取客户的条目
let fetchRequest=NSFetchRequest(entityName:“客户端”)
fetchRequest.returnsObjectsAsFaults=false
//使用谓词确保它是我需要的客户端
fetchRequest.predicate=NSPredicate(格式:“lastName==%@”,mylastName)
fetchRequest.predicate=NSPredicate(格式:“firstName==%@”,myfirstName)
fetchRequest.predicate=NSPredicate(格式:“地址=%@”,myaddress)
做{
var myClientToEdit=尝试managedContext.fetch(fetchRequest)
让myObject=myClientToEdit[0]
//我正确的客户已经打印出来了
打印(myObject)
//使用新条目设置新值
myObject.setValue(lastName.text!,forKey:“lastName”)
myObject.setValue(firstName.text!,forKey:“firstName”)
myObject.setValue(address.text!,forKey:“address”)
myObject.setValue(city.text!,forKey:“city”)
myObject.setValue(state.text!,forKey:“state”)
myObject.setValue(zip.text!,forKey:“zipCode”)
myObject.setValue(phoneDay.text!,forKey:“phoneDay”)
myObject.setValue(phoneEve.text!,forKey:“phoneweennight”)
myObject.setValue(email.text!,forKey:“email”)
做{
//拯救
请尝试managedContext.save()
}将let错误捕获为NSError{
打印(错误)
}
}将let错误捕获为NSError{
打印(错误)
}
//保存编辑后,将立即删除
self.disclose(动画:true,完成:nil)
}
当我回到我的详细客户vc时,我会做同样的事情,但只是读取核心数据。下面是vc客户端的详细代码

override func viewWillAppear(_ animated: Bool)
{
    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else
    {
        return
    }

    let managedContext = appDelegate.persistentContainer.viewContext

    let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Clients")

    fetchRequest.predicate = NSPredicate(format: "lastName == %@", myLastName)
    fetchRequest.predicate = NSPredicate(format: "firstName == %@", myFirstName)
    fetchRequest.predicate = NSPredicate(format: "address == %@", myAddress)

    do {
        var thisIsTheClient = try managedContext.fetch(fetchRequest)
        let myObject = thisIsTheClient[0]

        print(myObject)

        lastNameLabel.text = myObject.value(forKey: "lastName") as? String
        firstNameLabel.text = myObject.value(forKey: "firstName") as? String
        myCityLabel.text = myObject.value(forKey: "city") as? String
        myAddressLabel.text = myObject.value(forKey: "address") as? String
        myStateLabel.text = myObject.value(forKey: "state") as? String
        myZipLabel.text = myObject.value(forKey: "zipCode") as? String
        myDayLabel.text = myObject.value(forKey: "phoneDay") as? String
        myEveLabel.text = myObject.value(forKey: "phoneEvening") as? String
        myEmailLabel.text = myObject.value(forKey: "email") as? String 

    }catch let error as NSError
    {
        print(error)
    }
}
覆盖函数视图将出现(u动画:Bool)
{
让appDelegate=UIApplication.shared.delegate作为?appDelegate else
{
返回
}
让managedContext=appDelegate.persistentContainer.viewContext
let fetchRequest=NSFetchRequest(entityName:“客户端”)
fetchRequest.predicate=NSPredicate(格式:“lastName==%@”,myLastName)
fetchRequest.predicate=NSPredicate(格式:“firstName==%@”,myFirstName)
fetchRequest.predicate=NSPredicate(格式:“地址==%@”,myAddress)
做{
var thisIsTheClient=try managedContext.fetch(fetchRequest)
让myObject=this为客户端[0]
打印(myObject)
lastnamelab.text=myObject.value(forKey:“lastName”)为?字符串
firstnamelab.text=myObject.value(forKey:“firstName”)为?字符串
myCityLabel.text=myObject.value(forKey:“city”)作为?字符串
myAddressLabel.text=myObject.value(forKey:“地址”)为?字符串
myStateLabel.text=myObject.value(forKey:“state”)为?字符串
myZipLabel.text=myObject.value(forKey:“zipCode”)作为?字符串
myDayLabel.text=myObject.value(forKey:“phoneDay”)作为?字符串
myEveLabel.text=myObject.value(forKey:“phonenight”)作为?字符串
myEmailLabel.text=myObject.value(forKey:“电子邮件”)为?字符串
}将let错误捕获为NSError
{
打印(错误)
}
}
错误在以下行:让myObject=thisIsTheClient[0]。但只有当我尝试编辑地址时。这就是客户端也是在类下定义的。我知道索引超出范围与试图将某个内容放在与数组中完全不同的位置有关,但我不明白为什么只有在我尝试编辑地址时才会这样做。所有其他条目都会完全更新

2017年7月19日编辑


谢谢大家的回复!Maor和Jay都做对了谓词。我只是在客户端上搜索地址,而不是前三个属性。在Jay写了关于var的注释之后,我能够将新数据传回,更新var并搜索新记录。再次感谢

我敢肯定,为了组合谓词,您必须使用复合谓词,而不仅仅是试图更改fetch请求的属性:

let predicate1:NSPredicate = NSPredicate("label = 'foo'")
let predicate2:NSPredicate = NSPredicate("label = 'bar'")
let compound:NSCompoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate1,predicate2])

我认为你的问题与你想象的不同。 首先,当你写作时:

fetchRequest.predicate = NSPredicate(format: "lastName == %@", myLastName)
fetchRequest.predicate = NSPredicate(format: "firstName == %@", myFirstName)
fetchRequest.predicate = NSPredicate(format: "address == %@", myAddress)
只考虑最后一行,因为它覆盖了它前面的任何内容,这意味着在您的情况下,它将只查找address属性(我猜这就是为什么您认为您的问题只存在于address字段中…) 您应该按照@Jay提供的方法来创建复合谓词


第二件事(如果我理解正确的话)是,您将地址更改为myAddressLabel.text中包含的任何文本,并将其保存。但是,当您在detail vc上读取核心数据时,仍然尝试通过“MyAddress”变量进行查询,这与您保存的变量不同。如果是这样的话,那么它就解释了为什么会出现这个错误消息——它只是没有找到任何与搜索匹配的内容,所以当您尝试从空数组中获取第一个元素时,它会告诉您它超出了范围…

您试过调试SQL操作吗?看起来像是使用addres执行的SQL操作