如何通过关系设置实体属性?

时间:2016-11-30 15:18:25

标签: swift core-data entity relationship

我有以下实体和关系

enter image description here

我希望能够将练习设置为常规名称关系的nil结果,如果这有意义的话?以便以后可以在形成例程实体时将其设置为例程名称。

我的问题是,你如何设置这种属性?我正在尝试以下代码,但它会导致致命的崩溃:

userExercise.usersroutine?.name = nil

我的逻辑是我参加练习并遵循与name属性的关系并将其设置为nil?

感谢您对我的逻辑进行任何更正和澄清

编辑:添加了我现有的练习和例行保存功能

    func createExercise() {
    guard let managedObjectContext = managedObjectContext else { return }
   if let userExercise = userExercise {
        userExercise.name = userExerciseName.text
        userExercise.sets = Int64(userSetsCount)
        userExercise.reps = Int64(userRepsCount)
        userExercise.weight = Double(self.userExerciseWeight.text!)!
        userExercise.id = UUID().uuidString
        userExercise.routine = nil
    }
    do {
        try managedObjectContext.save()
    } catch {
        fatalError("Failure to save context: \(error)")
    }
}

常规创作:

    func createRoutine() {

    guard let managedObjectContext = managedObjectContext else { return }
    let userRoutine = UserRoutine(context: managedObjectContext)
    userRoutine.name = workoutNameTextfield.text

    do {
        try managedObjectContext.save()
    } catch {
        fatalError("Failure to save context: \(error)")
    }
}

当前获取请求:

    fileprivate lazy var fetchedResultsController: NSFetchedResultsController<UserExercise> = {

    let fetchRequest: NSFetchRequest<UserExercise> = UserExercise.fetchRequest()
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: "id", ascending: true)]
    let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.persistentContainer.viewContext, sectionNameKeyPath: nil, cacheName: nil)
    fetchedResultsController.delegate = self
    return fetchedResultsController

2 个答案:

答案 0 :(得分:1)

请检查下面的实施我已经创建了一些练习和例程。同时阅读代码中的注释,这将有助于您弄清楚如何去做。

添加新练习的功能

func createExercise(weight: Int16, respetitions: Int16, name: String, routine: Routine?)->Exercise? {
    let context = getMainContext()
    let exercise = NSEntityDescription.insertNewObject(forEntityName: "Exercise", into: context) as! Exercise
    exercise.setValue(weight, forKey: "weight")
    exercise.setValue(name, forKey: "name")
    exercise.setValue(respetitions, forKey: "rep")

    do {
        try context.save()
        return exercise
    }
    catch
    {
        fatalError("unable to Ssavve")
    }
}

添加新例程的功能

func createRoutine(name: String, exercises:[Exercise]) {
    let context = getMainContext()
    let routine = NSEntityDescription.insertNewObject(forEntityName: "Routine", into: context) as! Routine
    routine.name = name

    //Iterate over Exercise objects & check if routine is nil. 
   //Here if routine is not nil it menas your exercise is already assigned to a routine. 
   //If routine is nil assign routine.addToRelationship(<#T##value: Exercise##Exercise#>) and Also assign routine to the execise.

     do {
            try context.save()
        }
        catch
        {
            fatalError("unable to Ssavve")
        }

}

获取主NSManagedObjectContext的函数,我们可以在其上执行核心数据操作

func getMainContext() -> NSManagedObjectContext {
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    return appDelegate.persistentContainer.viewContext
}

下面,首先我创建一些与例程没有任何关系的练习

  

&#34;创建练习时,例程不存在,之后创建练习并设置其名称&#34;

然后通过传递一些练习(You can refer to other answer on how to fetch exercises with routine as nil values

来创建例程
func initializer() {
        //I'm adding exercises first without routines
        let ex1 = self.createExercise(weight: 10, respetitions: 4, name: "Exercise1", routine: nil)
        let ex2 = self.createExercise(weight: 5, respetitions: 10, name: "Exercise2", routine: nil)
        let ex3 = self.createExercise(weight: 20, respetitions: 2, name: "Exercise3", routine: nil)
        let ex4 = self.createExercise(weight: 5, respetitions: 10, name: "Exercise2", routine: nil)

        self.createRoutine(name: "Routine 1", exercises: [ex1!, ex2!]) //You can pass all the exercises or use fetch request to query exercises with routine as nil
        self.createRoutine(name: "Routine 2", exercises: [ex3!, ex4!])

        self.createRoutine(name: "Routine 3", exercises: [ex1!, ex2!]) //This routine shall not be adding any execises as they are already added to othe routines
    }

更新create routine函数以查询UserExercise的结果,其中usersroutine为nil

func createRoutine() {

    guard let managedObjectContext = managedObjectContext else { return }
    let userRoutine = UserRoutine(context: managedObjectContext)
    userRoutine.name = workoutNameTextfield.text

//Getting nil value User Exercises        
    let request: NSFetchRequest<UserExercise> = UserExercise.fetchRequest()
                request.predicate = NSPredicate(format: "usersroutine == nil")
                do {
                    let appDelegate = UIApplication.shared.delegate as! AppDelegate
                    let context = appDelegate.persistentContainer.viewContext
                    let queryResults = try context.fetch(request)

                    //I like to check the size of the returned results!
                    print ("num of results = \(queryResults.count)")

                    //You need to convert to NSManagedObject to use 'for' loops
                    for exercise in queryResults as [NSManagedObject] {
                        //get the Key Value pairs (although there may be a better way to do that...
                        print("Exercise NAME: \(exercise.value(forKey: "name"))")
                    }
                } catch {
                    print("Error with request: \(error)")
                }


        do {
            try managedObjectContext.save()
        } catch {
            fatalError("Failure to save context: \(error)")
        }
    }

答案 1 :(得分:0)

您似乎根本不需要使用name属性。此属性应用于存储UserRoutine的实际名称,而不是基于任何关系。

核心数据中的实体之间的关系不依赖于实体的特定属性,而是依赖于实体本身。

  

&#34;我希望例程构建器查看练习并将关系中的所有练习导入nil&#34;

因此...

创建获取请求以获取UserExercise的所有不具有相关UserRoutine的实体(即userroutine为零)。

let orphanedExerciseFetchRequest = NSFetchRequest(entityName: "UserExercises")
orphanedExerciseFetchRequest.predicate = NSPredicate(format: "userroutine == nil)

执行此获取请求以获取UserExercises数组(没有相关例程)

let orphanedExercises = managedObjectContext.executeFetchRequest(orphanedExerciseFetchRequest())
  

&#34;使用归因练习创建例程&#34;

将提取的UserExercise权限属性userRoutine设置为您的例程(并且不要忘记在管理对象上下文中保存更改)。

myRoutine.userexercises = orphanedExercises

稍后,如果您想要针对特定​​例程进行练习:

let fetchRequest = NSFetchRequest(entityName: "UserExercises")
fetchRequest.predicate = NSPredicate(format: "userroutine == %@", someUserRoutine)