核心数据似乎没有保存

时间:2019-03-15 01:04:25

标签: ios swift core-data

我正在尝试创建一个应用,要求用户在允许进入该应用的其余部分之前成功输入图钉。 我进行了一些搜索,找到了一个可以正常使用here的基本的现有coredata示例应用程序。

我进入xcdatamodel并删除了它们的属性,并替换为作为字符串的“ pin”。这是xcdatamodel的屏幕截图。xcdatamodel screenshot

然后,我修改了ViewController,以便createData UI按钮打开一个alertController,提示用户两次输入一个新的引脚,检查它们是否相同,如果相同,则使用该引脚创建一个coredata条目。

这是ViewController的相关代码:

import UIKit
import CoreData

class ViewController: UIViewController {
var firstPinNumber:String = ""
var secondPinNumber:String = ""

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

}

@IBAction func createData(_ sender: Any) {
    let enterPinAlertController = UIAlertController(title: "Enter New PIN", message: "", preferredStyle: .alert)
    enterPinAlertController.addTextField{ (textField1:UITextField)->Void in
        textField1.placeholder = "Enter PIN"
        textField1.isSecureTextEntry = true
    }
    enterPinAlertController.addTextField{   (textField2:UITextField)->Void in
        textField2.placeholder = "Re-Enter PIN"
        textField2.isSecureTextEntry = true
    }
    let okAction = UIAlertAction(title: "OK", style: .cancel)   {(action) in
        if let textFields = enterPinAlertController.textFields  {
            let theTextFields = textFields as [UITextField]
            self.firstPinNumber = theTextFields[0].text!
            self.secondPinNumber = theTextFields[1].text!
            if self.firstPinNumber != self.secondPinNumber   {
                print ("PINs dont match!")
                let pinsDontMatchAlertController = UIAlertController(title: "PINs don't match!", message: "Try again", preferredStyle: .alert)
                let okAction = UIAlertAction(title: "OK", style: .cancel)   {(action) in
                }
                pinsDontMatchAlertController.addAction(okAction)
                self.present(pinsDontMatchAlertController, animated: true, completion: nil)
            }
        }
    }

    enterPinAlertController.addAction(okAction)
    self.present(enterPinAlertController, animated: true, completion: nil)
    createPIN(pinNum: secondPinNumber)


}
func createPIN(pinNum: String){

    //As we know that container is set up in the AppDelegates so we need to refer that container.
    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }

    //We need to create a context from this container
    let managedContext = appDelegate.persistentContainer.viewContext

    //Now let’s create an entity and new user records.
    let userEntity = NSEntityDescription.entity(forEntityName: "User", in: managedContext)!

    let user = NSManagedObject(entity: userEntity, insertInto: managedContext)
    user.setValue(pinNum, forKeyPath: "pin")
    print(user.value(forKey: "pin") as Any)


    //Now we have set the pin. The next step is to save it inside the Core Data

    do {
        try managedContext.save()

    } catch let error as NSError {
        print("Could not save. \(error), \(error.userInfo)")
    }
}

@IBAction func retrieveData(_ sender: Any) {
    let storedPin = retrievePIN()
    print(storedPin)
}

func retrievePIN()->String {
    var storedPin:String = ""

    //As we know that container is set up in the AppDelegates so we need to refer that container.
    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return "" }

    //We need to create a context from this container
    let managedContext = appDelegate.persistentContainer.viewContext

    //Prepare the request of type NSFetchRequest  for the entity
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "User")

    fetchRequest.fetchLimit = 1
//        fetchRequest.predicate = NSPredicate(format: "username = %@", "Ankur")
//        fetchRequest.sortDescriptors = [NSSortDescriptor.init(key: "email", ascending: false)]
//
    do {
        let result = try managedContext.fetch(fetchRequest)
        for data in result as! [NSManagedObject] {
            if data.value(forKey: "pin") != nil {
                storedPin = data.value(forKey: "pin") as! String
                print(storedPin)
            } else  {
                print ("Found nil")
            }
        }

    } catch {

        print("Failed")
    }
    return storedPin
}

使用断点,我已经确定它进入了createPin()函数,但是,即使在介绍了enterPinAlertController之后调用了createPin(),它也似乎在输入enterPinAlertController之前进入了该函数。

此外,如果我使用retrieveData UIButton,它将打印出“ Found nil”

因此,如果我的想法是正确的,它会创建一个空字符串或根本什么都没有的coredata条目? 我该如何解决这个问题,以便它创建一个coredata条目,并将用户输入的字符串作为新的pin,并在以后检索它?

1 个答案:

答案 0 :(得分:1)

您对createPin的调用必须在okAction的动作处理程序内 。就像您现在拥有的一样,secondPinNumber将在显示警报之前被调用,因此它将为空或nil,具体取决于初始化方式。

IBAction func createData(_ sender: Any) {
    let enterPinAlertController = UIAlertController(title: "Enter New PIN", message: "", preferredStyle: .alert)
    enterPinAlertController.addTextField{ (textField1:UITextField)->Void in
        textField1.placeholder = "Enter PIN"
        textField1.isSecureTextEntry = true
    }
    enterPinAlertController.addTextField{   (textField2:UITextField)->Void in
        textField2.placeholder = "Re-Enter PIN"
        textField2.isSecureTextEntry = true
    }
    let okAction = UIAlertAction(title: "OK", style: .cancel)   {(action) in
        if let textFields = enterPinAlertController.textFields,
           let firstPinNumber = textFields[0].text,
           let secondPinNumber = textFields[1].text,
           firstPinNumber == secondPinNumber {
               createPIN(pinNum: secondPinNumber)
            } else {
               print ("PINs dont match!")
               let pinsDontMatchAlertController = UIAlertController(title: "PINs don't match!", message: "Try again", preferredStyle: .alert)
               let okAction = UIAlertAction(title: "OK", style: .cancel)  
               pinsDontMatchAlertController.addAction(okAction)
               self.present(pinsDontMatchAlertController, animated: true, completion: nil)
            } 
        }
    }

    enterPinAlertController.addAction(okAction)
    self.present(enterPinAlertController, animated: true, completion: nil)

}