簡體   English   中英

更新CoreData實體或保存一個新實體

[英]Updating CoreData Entity or saving a new one

我是CoreData的新手,我正在嘗試制作游戲。 我有兩個問題,希望大家能通過一些指導幫助我:
-GameKit是否已經集成了某種CoreData? 我不確定如果我已經在GameKit中取代了CoreData,那么是否應該對CoreData有所考慮。
無論如何,假設上述問題的答案是“不。GameKit不能保存您的游戲”。 我將繼續執行當前的“保存游戲”代碼,如下所示:

func saveCurrentMatch()
    {
        /* CORE DATA STUFF:
         FIRST NEED TO VERIFY IF THIS GAME HAS BEEN PREVIOUSLY SAVED, IF SO THEN UPDATE, ELSE JUST SAVE
         Entity: MatchData
         Attributes: scoreArray (String), playerArray (String), myScore (Int), matchID (Int), isWaiting (Bool), isRealTime (Bool), gameLog (String)
         */

        let context = myAppDelegate.persistentContainer.viewContext
        let request = NSFetchRequest<NSFetchRequestResult>(entityName: "MatchData")
        request.returnsObjectsAsFaults = false

        do
        {
            let gamesInProgress = try context.fetch(request)
            print (gamesInProgress.count)

            if gamesInProgress.count > 0 //HERE CHANGE THIS TO LOOK FOR THE MATCH ID OF THIS GAME!!
            {
                gameExistsinCD = true
            }
            else
            {
                gameExistsinCD = false
            }
        }
        catch
        {
            print ("Error Reading Data: \(error.localizedDescription)")
        }

        if gameExistsinCD
        {
            //CODE TO UPDATE MATCH INSTEAD OF SAVING NEW ONE
        }
        else
        {
            // CODE TO SAVE A NEW MATCH FOR THE FIRST TIME
            let matchData = NSEntityDescription.insertNewObject(forEntityName: "MatchData", into: context)

            matchData.setValue(isRealTime, forKey: "isRealTime")
            matchData.setValue(currentScore?[0], forKey: "myScore")
            matchData.setValue(currentScore?.map{String($0)}.joined(separator: "\t"), forKey: "scoreArray") // IS THIS CODE CORRECT? I'M TRYING TO SAVE AN ARRAY OF INTS INTO A SINGLE STRING
            matchData.setValue(currentPlayers?.joined(separator: "\t"), forKey: "playerArray")
            matchData.setValue(true, forKey: "isWaiting") //will change later to update accordingly.
            matchData.setValue(matchID, forKey: "matchID")
            matchData.setValue(gameLog, forKey: "gameLog")

            do
            {
                try context.save()
                print ("CoreData: Game Saved!")
            }
            catch
            {
                print ("Error Saving Data: \(error.localizedDescription)")
            }
        }
    }

我主要關心的是獲取請求,如果已保存此匹配項,如何檢查所有核心數據? 如果是這樣,那么更新實體而不是插入新實體的代碼是什么?
任何指導表示贊賞,謝謝!

核心數據基本上是SQL數據庫的包裝器。 當您需要處理大量數據時,這非常有效。 因此,請考慮您是否有這樣的要求,否則將數據存儲為用戶默認設置或設置可能是明智的。

如果是這樣,那么您幾乎不需要知道什么。

  1. 創建您自己的模型類非常有用。 打開核心數據模型文件,打開“編輯器/創建NSManagedObject子類”。 它將允許您引用直接屬性,而不是KVC(setValue:forKey :)。
  2. 請始終注意您正在使用的線程。使用在其他線程中創建的對象是不安全的。
  3. 您的gamesInProgress包含從數據庫中獲取的對象數組。

所以基本上不是

  if gameExistsinCD
        {
            //CODE TO UPDATE MATCH INSTEAD OF SAVING NEW ONE
        }
        else
        {
            // CODE TO SAVE A NEW MATCH FOR THE FIRST TIME
            let matchData = NSEntityDescription.insertNewObject(forEntityName: "MatchData", into: context)
            matchData.setValue(isRealTime, forKey: "isRealTime")
            <...>

你可以做

let matchData =  (gamesInProgress.first ??      
NSEntityDescription.insertNewObject(forEntityName: "MatchData", into: context)) as! <YouEntityClass>  
matchData.isRealTime = isRealTime
<...>

PS: https : //www.raywenderlich.com/173972/getting-started-with-core-data-tutorial-2

不要讓核心數據嚇到您。 這是保存本地數據的一種好方法,盡管有一些注釋,但正確完成后並不慢。 實際上,核心數據可以非常快。

通過以更普通的方式使用Object類而不是使用setValue調用,可以大大簡化代碼。 您的創建代碼可以更改為:

// CODE TO SAVE A NEW MATCH FOR THE FIRST TIME
if let matchData = NSEntityDescription.insertNewObject(forEntityName: "MatchData", into: context) as? MatchData {

    matchData.isRealTime = isRealTime
    matchData.myScore = currentScore?[0]
    matchData.scoreArray = currentScore?.map{String($0)}.joined(separator: "\t") // IS THIS CODE CORRECT? I'M TRYING TO SAVE AN ARRAY OF INTS INTO A SINGLE STRING
    // You can certainly save it this way and code it in and out. A better alternative is to have a child relationship to another managed object class that has the scores.
    matchData.playerArray = currentPlayers?.joined(separator: "\t")
    matchData.isWaiting = true
    matchData.matchID = matchID
    matchData.gameLog = gameLog
}

這是設置對象屬性的一種更具可讀性和常規的方法。 每當您更改核心數據托管對象上的屬性時,下次保存上下文時,該屬性將被保存。

至於查找與ID匹配的當前記錄,我喜歡將這樣的類添加到我的Managed Object類中:

class func findByID(_ matchID: String) -> MatchData? {
    let myAppDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = myAppDelegate.persistentContainer.viewContext
    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "MatchData")
    let idPredicate = NSPredicate(format: "matchID = \(matchID)", argumentArray: nil)
    request.predicate = idPredicate
    var result: [AnyObject]?
    var matchData: MatchData? = nil
    do {
        result = try context.fetch(request)
    } catch let error as NSError {
        NSLog("Error getting match: \(error)")
        result = nil
    }
    if result != nil {
        for resultItem : AnyObject in result! {
            matchData = resultItem as? MatchData
        }
    }
    return matchData
}

然后,您需要通過ID匹配數據的任何地方都可以調用class函數:

if let matchData = MatchData.findByID("SomeMatchID") {
    // Match exists
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM