保存/获取 CoreData 关系 Swift 3

Posted

技术标签:

【中文标题】保存/获取 CoreData 关系 Swift 3【英文标题】:Saving/Fetching CoreData Relationships Swift 3 【发布时间】:2017-06-22 21:29:02 【问题描述】:

我正在制作一个用于学习的预算应用程序,我有几个关于在 CoreData 中存储和获取实体的问题。

我有两个实体“预算”和“费用”。

每个预算都有自己的费用。例如,我可以有一个“娱乐”预算,它可以有“保龄球”和“电影”等费用。

我可以创建预算并保存。然后加上费用。

let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let expense = Expense(context: context)
.
. // Filling out the expense here
.
budget?.addToExpense(expense)
(UIApplication.shared.delegate as! AppDelegate).saveContext()

然后我检索 Expenses 集合并在 TableView 中显示商店名称

// Inside cellForRowAt
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
let myArray = Array((budget?.expense)!)
cell.textLabel?.text = (myArray[indexPath.row] as! Expense).store
return cell

到目前为止一切顺利。我的问题是,当我存储费用时,它存储在一个集合中。这意味着当我检索该集合并将其类型转换为数组时,顺序是随机的。

我想要的是存储费用并以这样的方式检索它们,以便我可以在 TableView 中以 FIFO 顺序显示费用。换句话说,我在预算中添加的第一笔费用应该是表格视图中的第一个元素,依此类推。

【问题讨论】:

【参考方案1】:

可能有几种方法可以实现这一目标。最直接的方法是对expense 使用有序关系。

为此,

在 DataModel 编辑器中打开 expense 关系属性。 检查订购选项

那么budget.expense将不是Set,而是OrderedSet,你不需要将其转换为Array,而是直接通过索引访问。

【讨论】:

漂亮!谢谢!【参考方案2】:

浏览器控制器 1: =====================>

导入核心数据

类视图控制器:UIViewController

@IBOutlet weak var txt_user: UITextField!





@IBOutlet weak var txt_password: UITextField!



var result = NSArray()



override func viewDidLoad() 

    super.viewDidLoad()

    // Do any additional setup after loading the view, typically from a nib.



    txt_password.isSecureTextEntry = true









@IBAction func login_action(_ sender: Any)



   if(txt_user.text == "" || txt_password.text == "")

   

    let alert = UIAlertController(title: "info", message: "fields are empty", preferredStyle: .alert)

    let ok = UIAlertAction(title: "OK", style: .default, handler: nil)

    alert.addAction(ok)

    self.present(alert, animated: true, completion: nil)



    

    else

   

    self.CheckForUserNameAndPasswordMatch(empName: txt_user.text! , empPwd: txt_password.text!)

    









func CheckForUserNameAndPasswordMatch(empName:String,empPwd:String)



    let app = UIApplication.shared.delegate as! AppDelegate

    let context = app.persistentContainer.viewContext





    let fetchdata = NSFetchRequest<NSManagedObject>(entityName: "Employee")

    let predicate = NSPredicate(format: "empName = %@",empName)

    fetchdata.predicate = predicate

    do

    

        self.result = try context.fetch(fetchdata as! NSFetchRequest<NSFetchRequestResult>)as NSArray

        if result.count>0

        

            let objcetEntity = result.firstObject as! Employee





            if objcetEntity.empName == empName && objcetEntity.empPwd == empPwd

            

                print("Login Successfully")

                // Entered Username & password matched

            

            else

            

                print("Wrong password/username")



                //Wrong password/username

            



        

    

    catch let error as NSError

    

        print("error",error.localizedDescription)

    







 @IBAction func unwindToVC1(sender:UIStoryboardSegue)

 

    if sender.source is ViewController2

    

        let secvc = sender.source as! ViewController2

        txt_password.text = secvc.str1! as String

    




视图控制器 2:

=====================>

类 ViewController2: UIViewController ,UITextFieldDelegate

@IBOutlet weak var txt_name: UITextField!



@IBOutlet weak var txt_mail: UITextField!



@IBOutlet weak var txt_pwd: UITextField!



@IBOutlet weak var txt_cpwd: UITextField!



@IBOutlet weak var txt_phone: UITextField!



@IBOutlet weak var err: UILabel!



var str1:NSString!

var str2:NSString!



//var update:NSManagedObject!







override func viewDidLoad() 

    super.viewDidLoad()



    /*if(update != nil)

    

    txt_name.text = update.value(forKey: "empName") as? String

    txt_mail.text = update.value(forKey: "empMail") as? String

    txt_pwd.text = update.value(forKey: "empPwd") as? String

    txt_cpwd.text = update.value(forKey: "empCpwd") as? String

    txt_phone.text = update.value(forKey: "empPhone") as? String

    */



    txt_pwd.isSecureTextEntry = true

    txt_cpwd.isSecureTextEntry = true









override func viewWillAppear(_ animated: Bool)



    txt_name.becomeFirstResponder()











@IBAction func regis_clicked(_ sender: Any)





    if(txt_name.text == "" || txt_mail.text == "" || txt_pwd.text == "" || txt_cpwd.text == "" || txt_phone.text == "" )

    

        let alert = UIAlertController(title: "information", message: "fields are empty", preferredStyle: .alert)

        let ok = UIAlertAction(title: "OK", style: .default, handler:

        

           (actionsheet) in



            if(self.txt_name.text == "")

            

                self.txt_name.becomeFirstResponder()

            

            if(self.txt_mail.text == "")

            

                self.txt_mail.becomeFirstResponder()

            

            if(self.txt_pwd.text == "")

            

                self.txt_pwd.becomeFirstResponder()

            

            if(self.txt_cpwd.text == "")

            

                self.txt_cpwd.becomeFirstResponder()

            

            if(self.txt_phone.text == "")

            

                self.txt_phone.becomeFirstResponder()

            

        )



        let cancel = UIAlertAction(title: "cancel", style: .default, handler: nil)

        alert.addAction(ok)

        alert.addAction(cancel)



        self.present(alert, animated: true, completion: nil)

    



    else if(txt_pwd.text != txt_cpwd.text)

    



        let alert1 = UIAlertController(title: "information", message: "password mismatched", preferredStyle: .alert)

        let ok = UIAlertAction(title: "OK", style: .default, handler:nil)

        let cancel = UIAlertAction(title: "cancel", style: .default, handler: nil)

        alert1.addAction(ok)

        alert1.addAction(cancel)

        self.present(alert1, animated: true, completion: nil)

    

    else

    



        let app = UIApplication.shared.delegate as! AppDelegate



        let context = app.persistentContainer.viewContext



        let newuser = NSEntityDescription.insertNewObject(forEntityName: "Employee", into: context)

        newuser.setValue(txt_name.text, forKey: "empName")

        newuser.setValue(txt_mail.text, forKey: "empMail")

         newuser.setValue(txt_pwd.text, forKey: "empPwd")

         newuser.setValue(txt_cpwd.text, forKey: "empCpwd")

         newuser.setValue(txt_phone.text, forKey: "empPhone")



        do

        

            try context.save()

        

        catch let error as NSError

        

            print("error",error.localizedDescription)

        



    

   // self.navigationController?.popViewController(animated: true)

    performSegue(withIdentifier: "unwind", sender: self)


override func prepare(for segue: UIStoryboardSegue, sender: Any?)



    if let newlabel = txt_pwd.text

    

        str1 = newlabel as NSString

    


【讨论】:

以上是关于保存/获取 CoreData 关系 Swift 3的主要内容,如果未能解决你的问题,请参考以下文章

Swift CoreData 保存一对一的关系

Swift CoreData,通过多对多关系保存数据

Swift、CoreData 和多对多关系:如何访问子项的顺序?

在 Swift4 中将获取的 XMPPframeWork vCards 保存到 CoreData

如何从 Swift 的后台线程中从 CoreData 中获取未保存的数据?

Coredata / SWIFT 获取有关系的记录