Search code examples
swiftxcodecore-dataswiftuipreview

SwiftUI Preview Core Data with Relationships


I'm trying to work with Core Data & SwiftUI's previews and think I'm close but haven't been able to get this to work.

    static var previews: some View {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        let newGame = Game.init(context: context)
        newGame.gameName = "Testy Game"
        newGame.gameDescription = "Wooo play the thing"
        newGame.goal = Goal.init(goalName: "Try Harder", goalComplete: false, goalOfGame: newGame)
        return GameGoalsDetail(game: newGame).environment(\.managedObjectContext, context)
    }
}

I'm getting a "Ambiguous reference to member 'init(entity:insertInto:)'" on the newGame.Goal = Goal.init... line.

I'm trying to figure out how to initialize a new Game and then initialize a connected Goal to it right after.

My Core Data Game class takes gameName, gameDescription, and a goal as a NSSet?. The Core Data Goal class has goalName, goalComplete, & goalOfGame: Game?. I think my issue is in connecting the two.

Appreciate the help in advance and willing to share more code if requested.


Solution

  • The Goal is @NSManagedObject thats why you need to use its init with context. When tou create an entity object, you must place it in some store - context is that store. After that you can cast all the properties you need including links.

    let goal = Goal(context: context)
    goal.goalName = "Try Harder"
    goal.goalComplete = false
    goal.goalOfGame = newGame
    return GameGoalsDetail(game: newGame).environment(\.managedObjectContext, context)
    

    if you set reversed links in data model, there is no need to use add-methods generated by CoreData, if you have at least 1 one-to-one link. You just set this link as a property value and CoreData do all the work for you. goal.goalOfGame is that property - reverced link one-to-one to it parent.

    If you realy want to use init with all the property you want to cast, just override it in extention to your class like this:

    extention Goal{
        init(of game: Game, name: String = "unnamed", complete: Bool = false, context: NSManagedObjectContext  
        ){
            super.init(context: context)
            self.goalOfGame = game
            self.goalName  = name
            self.complete = goalComplete 
        }
    }