CoreData Swift:如何保存和加载数据?

20

我正在使用Swift编写iOS游戏,并希望在结束时包含一个高分榜标签。我认为保存功能是正确的,但加载功能是出问题的。我已经创建了一个实体("BestScores")和属性("classicBestScoreTF"):

保存高分榜:

var bestscore25 = 1000
var score: int

func savescore() {    
    var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
    var context:NSManagedObjectContext = appDel.managedObjectContext!
    var score25: AnyObject! = NSEntityDescription.insertNewObjectForEntityForName("BestScores", inManagedObjectContext: context) as NSManagedObject
    score25.setValue(score, forKey: "classicBestScoreTF")
    context.save(nil)
}

func loadscore() {
    var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
    var context:NSManagedObjectContext = appDel.managedObjectContext!
    bestScore25 = valueForKey("classicBestScoreTF") as Int
}

func endgame() {

    if score > bestScore25 {
        savescore()
        loadscore()
        bestScoreLabel.text = "Best Score: \(bestScore25)"
    }

    if score < bestscore {            
        loadscore()
        bestScoreLabel.text = "Best Score: \(bestScore25)"
    }    
}

无法正常工作 :( 请帮忙!


你可以通过传递并在保存期间评估错误对象来开始。 - vikingosegundo
7个回答

31

保存数据:

var person = NSEntityDescription.insertNewObjectForEntityForName("Person", 
inManagedObjectContext: self.managedObjectContext!) as Person
person.name = "Mary"
person.age = Float(arc4random() % 100)

var error : NSError? = nil
if !self.managedObjectContext!.save(&error) {
    NSLog("Unresolved error \(error), \(error!.userInfo)")
    abort()
}

加载数据:

var error: NSError? = nil
var fReq: NSFetchRequest = NSFetchRequest(entityName: "Frases")    
fReq.predicate = NSPredicate(format: "id contains[c] %@", String(day))
var sorter: NSSortDescriptor = NSSortDescriptor(key: "id" , ascending: false)
fReq.sortDescriptors = [sorter]
fReq.returnsObjectsAsFaults = false
let result : [AnyObject] = self.managedObjectContext!.executeFetchRequest(fReq, error:&error)!

3
在插入新对象后,难道不需要调用 save() 吗? - MarksCode

11

Swift 5

步骤1. 使用CoreData选项创建简单的应用程序。

enter image description here

步骤2. 打开.xcdatamodeld文件,并以此方式添加实体属性

enter image description here

步骤3. 您的AppDelegate应该有Core Data stack methods(核心数据堆栈方法)

步骤4. 确保您具有以下Swift代码片段

import UIKit
import CoreData

class ViewController: UIViewController {

    // MARK: Variables declearations
    let appDelegate = UIApplication.shared.delegate as! AppDelegate //Singlton instance
    var context:NSManagedObjectContext!

    // MARK: View Controller life cycle methods
    override func viewDidLoad() {
        super.viewDidLoad()

        openDatabse()
    }

    // MARK: Methods to Open, Store and Fetch data
    func openDatabse()
    {
        context = appDelegate.persistentContainer.viewContext
        let entity = NSEntityDescription.entity(forEntityName: "Users", in: context)
        let newUser = NSManagedObject(entity: entity!, insertInto: context)
        saveData(UserDBObj:newUser)
    }

    func saveData(UserDBObj:NSManagedObject)
    {
        UserDBObj.setValue("RDC", forKey: "username")
        UserDBObj.setValue("1234", forKey: "password")
        UserDBObj.setValue("21", forKey: "age")

        print("Storing Data..")
        do {
            try context.save()
        } catch {
            print("Storing data Failed")
        }

        fetchData()
    }

    func fetchData()
    {
        print("Fetching Data..")
        let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
        request.returnsObjectsAsFaults = false
        do {
            let result = try context.fetch(request)
            for data in result as! [NSManagedObject] {
                let userName = data.value(forKey: "username") as! String
                let age = data.value(forKey: "age") as! String
                print("User Name is : "+userName+" and Age is : "+age)
            }
        } catch {
            print("Fetching data Failed")
        }
    }
}

第五步。在设备上运行并查看核心数据结果的日志


最佳答案!谢谢! - Silvering

4

更新为Swift版本:

使用以下简单代码来加载、插入和删除数据;

import UIKit
import CoreData

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate{

    // MARK:- Variable Declarations

    @IBOutlet weak var mTableView: UITableView!
    var manageObjectContext: NSManagedObjectContext!
    var eventArray = [Event]()

    // MARK:- ViewController LifeCycle Methods

    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "Event Reminder"
        manageObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        self.loadSaveData()
    }

    override func viewWillAppear(_ animated: Bool) {
        // Remove empty cell from tableview
        mTableView.tableFooterView = UIView(frame: .zero)
    }

    // MARK:- TableView DataSource and Delegate Methods

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return eventArray.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "ViewControllerTableViewCell")! as! ViewControllerTableViewCell
        cell.layer.cornerRadius = 05

        let eventArrayItem = eventArray[indexPath.row]

        if let eventImage = UIImage(data: (eventArrayItem.event_image! as Data)){
            cell.mImageView.image = eventImage
        }

        cell.mEventHeadingLabel.text = eventArrayItem.event_heading
        cell.mShortDescriptionLabel.text = eventArrayItem.event_description

        return cell
    }

    // To delete Particular cell/row from tableview
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

        let eventArrayItem = eventArray[indexPath.row]

        if editingStyle == .delete {
            manageObjectContext.delete(eventArrayItem)

            do {
                try manageObjectContext.save()
            } catch let error as NSError {
                print("Error While Deleting Note: \(error.userInfo)")
            }
        }
        self.loadSaveData()
    }

    // MARK:- IBAction Methods

    @IBAction func actionOnPlusButton(_ sender: Any) {
        let imagePicker = UIImagePickerController()
        imagePicker.sourceType = .photoLibrary
        imagePicker.delegate = self
        self.present(imagePicker, animated: true, completion: nil)
    }

    // MARK:- ImagePicker Delegate Methods

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

        if let mImage = info[UIImagePickerControllerOriginalImage] as? UIImage{
            picker.dismiss(animated: true, completion: { 
                self.createEventItemWith(selectedImage: mImage)
            })
        }
    }

    // MARK:- Instance Methods

    func createEventItemWith(selectedImage: UIImage)  {

        let eventItem = Event(context: manageObjectContext)

        let alertController = UIAlertController(title: "Add Event", message: "Enter event and it's description", preferredStyle: .alert)

        let saveAction = UIAlertAction(title: "Save", style: .default, handler: {
            alert -> Void in

            let eventNameTextField = alertController.textFields![0] as UITextField
            let descriptionTextField = alertController.textFields![1] as UITextField

            print("firstName \(String(describing: eventNameTextField.text)), secondName \(String(describing: descriptionTextField.text))")

            if eventNameTextField.text != "" || descriptionTextField.text != ""{

                eventItem.event_heading = eventNameTextField.text
                eventItem.event_description = descriptionTextField.text
                eventItem.event_image = NSData(data: UIImageJPEGRepresentation(selectedImage, 0.3)!)

                do{
                    try self.manageObjectContext.save()
                    self.loadSaveData()
                }catch{
                    print("Could not save data: \(error.localizedDescription)")
                }

            }else{
                self.showAlertMessageToUser(title: "Alert", messageToUser: "Fields should not be empty, Please enter given info...")
            }
        })

        let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: {
            (action : UIAlertAction!) -> Void in
                self.manageObjectContext.reset()
        })

        alertController.addTextField { (textField : UITextField!) -> Void in
            textField.placeholder = "Enter event Name"
        }
        alertController.addTextField { (textField : UITextField!) -> Void in
            textField.placeholder = "Enter event description in short"
        }

        alertController.addAction(saveAction)
        alertController.addAction(cancelAction)

        self.present(alertController, animated: true, completion: nil)
    }

    func showAlertMessageToUser(title: String, messageToUser: String)  {
        let alert = UIAlertController(title: title, message: messageToUser, preferredStyle: UIAlertControllerStyle.alert)
        alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
        self.present(alert, animated: true, completion: nil)
    }

    func loadSaveData()  {
        let eventRequest: NSFetchRequest<Event> = Event.fetchRequest()
        do{
            eventArray = try manageObjectContext.fetch(eventRequest)
            self.mTableView.reloadData()
        }catch
        {
            print("Could not load save data: \(error.localizedDescription)")
        }
    }
}

enter image description here


3

为了保存数据,应该使用以下方法:

context.insertNewObjectForEntityForName(...)

并且加载数据时,应该是这样的:
context.valueForKey(...)
然而,我不确定那是否是正确的语法,因为你可能需要获取实体的数组,然后获取索引为0的对象。另外,为什么要使用Core Data来存储高分数呢?你可以考虑使用用户默认设置或iCloud,Core Data更适用于数据库。

如果这让您感到困惑,我可以提供示例代码,请告诉我。 - steffeydev
不是 context.insertNewObjectForEntityForName...,而是 NSEntityDescription.insertNewEntyty : inManagedObjectContext: ... - Massmaker

2

导入UIKit 导入CoreData

类ViewController:UIViewController {

let nameTxt: UITextField = {

    let td = UITextField()
    td.translatesAutoresizingMaskIntoConstraints = false
    td.placeholder = "Enter Id"
    td.borderStyle = .line
    td.layer.borderWidth = 1
    td.layer.borderColor = UIColor.lightGray.cgColor
    return td
}()

let doneBt: UIButton = {

    let bt = UIButton()
    bt.translatesAutoresizingMaskIntoConstraints = false
    bt.setTitle("DONE", for: .normal)
    bt.setTitleColor(.white, for: .normal)
    bt.addTarget(self, action: #selector(handleDoneBt), for: .touchUpInside)
    bt.backgroundColor = UIColor.blue
    return bt
}()

@objc func handleDoneBt() {

     saveData()
}

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

    setupView()
    setupLayout()

}


func saveData() {

    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {return}

    let manageContent = appDelegate.persistentContainer.viewContext

    let userEntity = NSEntityDescription.entity(forEntityName: "Users", in: manageContent)!

    let users = NSManagedObject(entity: userEntity, insertInto: manageContent)

    users.setValue(1, forKeyPath: "id")
    users.setValue(nameTxt.text, forKeyPath: "name")
    users.setValue(123, forKeyPath: "mobile")


    do{
        try manageContent.save()
    }catch let error as NSError {

        print("could not save . \(error), \(error.userInfo)")
    }

    fetchData()
}

func fetchData() {

    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {return}
     let manageContent = appDelegate.persistentContainer.viewContext
     let fetchData = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")

    do {

        let result = try manageContent.fetch(fetchData)

        for data in result as! [NSManagedObject]{

             print(data.value(forKeyPath: "id") as Any)
             print(data.value(forKeyPath: "name") as Any)
        }
    }catch {
        print("err")
    }
}

func setupView() {

    view.addSubview(nameTxt)
    view.addSubview(doneBt)
}
func setupLayout(){

    NSLayoutConstraint.activate([

            nameTxt.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            nameTxt.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            nameTxt.widthAnchor.constraint(equalToConstant: 160),
            nameTxt.heightAnchor.constraint(equalToConstant: 30),

            doneBt.topAnchor.constraint(equalTo: nameTxt.bottomAnchor,constant: 6),
            doneBt.leftAnchor.constraint(equalTo: nameTxt.leftAnchor,constant: 8),
            doneBt.widthAnchor.constraint(equalToConstant: 120),
            doneBt.heightAnchor.constraint(equalToConstant: 36)
        ])
}

}

在TableView中显示

func fetchData() {

    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {return}
    let manageContent = appDelegate.persistentContainer.viewContext
    let fetchData = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")        
    do {

        let result = try manageContent.fetch(fetchData)
        allData = result as! [NSManagedObject]
        tbl.reloadData()
    }catch {
        print("err")
    }
}

var allData = [NSObject]()

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return allData.count }

在编程中,返回表格视图的行数时,可以使用此函数。该函数接受一个UITableView对象和一个整数类型的参数section作为输入,并返回一个整数类型的值,即allData数组的元素数量。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! tblCell
    cell.lbl.text = allData[indexPath.row].value(forKey: "name") as? String
    return cell
}

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {

在UITableView中,返回UITableViewCell的编辑风格和索引路径。

    if editingStyle == .delete {
        let task = allData[indexPath.row]
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {return}

        let manageContent = appDelegate.persistentContainer.viewContext

        manageContent.delete(task as! NSManagedObject)
        (UIApplication.shared.delegate as! AppDelegate).saveContext()

        do {
            try manageContent.save()
        } catch {
            print("Fetching Failed")
        }
    }
    fetchData()
}

0

CoreData 操作

import CoreData


public class ItemCoreDataStorage {
    
    let context: NSManagedObjectContext
    
    init(context: NSManagedObjectContext) {
        self.context = context
    }
    
    func save(_ items: [Item]) {
        
        cashbackItems.forEach({ item in
            let moItem = MOCashback(context: context)
            moItem.a = item.a
            moItem.b = item.b
        })
        
        do {
            try context.save()
        } catch {
            //Error handling
        }
        
    }
    
    func fetch() -> [MOItem] {
        do {
            let moItems: [MOItem] = try context.fetch(MOItem.fetchRequest())
            return moItems
        } catch {
            //Error handling
        }
    }
    
    func fetchedResultsController() -> NSFetchedResultsController<MOItem> {
        
        let fetchRequest: NSFetchRequest< MOItem > = MOCashback.fetchRequest()
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "a", ascending: true)]
        let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
        
        return frc
    }
    
    func delete() {

        self.fetch()
            .forEach({ context.delete($0)})
        do {
            try context.save()
        }
        catch {
            //Error handling
        }

    }
}
  • 请注意,您可以使用“bunch”来删除项目,但它不会由FRC管理。

  • 此外,fetchRequest.sortDescriptors是必需的。


-1

导入UIKit

class tblviewAViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {

@IBOutlet weak var tablviwREA: UITableView!
var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var studentarry:[StudentsFR] = []

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return studentarry.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "tblCA", for: indexPath)as! tblcellATableViewCell
    let onrecord = studentarry[indexPath.row]
    //cell.textLabel?.text =
   
    cell.lblREA.text = onrecord.st_name!
    cell.LBLREB.text = onrecord.st_address!
     cell.lblREC.text = onrecord.st_email!
   cell.lblRED.text = onrecord.st_department!
    cell.lblREE.text = onrecord.st_course!
    cell.lblREF.text = onrecord.st_school!
    
    
    
    
    
    return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 100
}




func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete{
        let std = studentarry[indexPath.row]
        context.delete(std)
        (UIApplication.shared.delegate as! AppDelegate).saveContext()
        do{
            studentarry = try context.fetch(StudentsFR.fetchRequest())
            
        }catch{
            print("error")
            
        }
    }
    tableView.reloadData()
}
func fetchdata(){
    do{
        studentarry = try context.fetch(StudentsFR.fetchRequest())
        
    }catch{
        print("error")
    }




}

override func viewDidLoad() {
    super.viewDidLoad()
    
    
    self.fetchdata()
    self.tablviwREA.reloadData()
    // Do any additional setup after loading the view.
}

}


在另一个视图控制器中的表格视图单元格中显示核心数据。 - mAj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接