更新CoreData实体或保存新实体

时间:2018-01-08 11:43:34

标签: ios swift xcode core-data

我对CoreData很新,而且我正试图制作一款游戏。我有几个问题我希望你们可以帮助我一些指导:
- GameKit是否已经集成了某种CoreData?我不确定我是否正在过度思考这个CoreData的东西,如果已经有一些东西在GameKit中取而代之的话。 。 。 。
无论如何,假设上述问题的答案是"没有。 GameKit没有什么可以保存你的游戏"。我将继续我目前的#34; Save game"代码如下:

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)")
            }
        }
    }

我主要关心的是获取请求,如果已经保存了这个匹配,如何检查所有核心数据?如果是这样,那么更新实体的代码是什么,而不是插入一个实体? 感谢任何指导,谢谢!

2 个答案:

答案 0 :(得分:1)

核心数据基本上是围绕SQL数据库。当您处理需要存储的大量数据时,它非常有效。因此,请考虑您是否有这样的要求,否则将数据存储在用户默认值或设置中可能是明智之举。

如果是,您需要知道的事情很少。

  1. 创建自己的模型类非常有用。打开核心数据模型文件,打开&#34;编辑/创建NSManagedObject子类&#34;。它将允许您引用直接属性,而不是KVC(setValue:forKey :)。
  2. 总是介意你正在使用什么线程。使用在其他线程中创建的对象是不安全的。
  3. 您的 gamesInProgress 包含从数据库中提取的对象数组。
  4. 所以基本上不是

      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

答案 1 :(得分:1)

不要让Core Data吓到你。它可以是一种保存本地数据的好方法,尽管有一些注释,但如果做得好,它也不会很慢。事实上,核心数据可以非常快。

通过以更常规的方式使用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获取匹配数据的任何地方,您可以调用类函数:

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