2016-11-30 8 views
0

私は、次のエンティティとの関係関係を介してエンティティ属性を設定するにはどうすればよいですか?

enter image description here

は、私はそれが理にかなっている場合は、そのルーチン名の関係についてはnil結果を持っている運動を設定できるようにしたいですか?ルーチン実体が形成されたときに後でそれをルーチン名として設定することができる。

私の質問は、この種の属性をどのように設定するかです。私は、次のコードをしようとしていますが、それは致命的なクラッシュが発生します。

userExercise.usersroutine?.name = nil 

私は運動を取り、nameプロパティとの関係を追跡し、nilに設定することをされて私のロジック?私のロジック上の任意の訂正と明確化

EDITため

ありがとう:私の既存の運動や日常保存機能を追加しました

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 
+0

をごusersroutine値自体はnilであると、あなたがそれの上に名前を設定しようとしているためです。意味がありますか?まず、ルーチンに値を代入し、必要に応じてnameをnilに設定します。 –

+0

私は理解しています。正しい方法は何でしょうか?私が設定する名前があるまで、単純にuserExercise.usersroutine = nilを使用しますか? – infernouk

+0

ルーチンとエクササイズの間にどのような関係を持たせたいのかを説明して、あなたの問題をよりよく理解し、実行可能な解決策を提供することができますか? –

答えて

1

以下の実装を確認してください。私はいくつかの演習とルーチンを作成しました。また、コード内のコメントを読んでください、これはあなたがそれについて行く方法を理解するのに役立ちます。我々はコア・データアクション

func getMainContext() -> NSManagedObjectContext { 
    let appDelegate = UIApplication.shared.delegate as! AppDelegate 
    return appDelegate.persistentContainer.viewContext 
} 
を実行できる上、メインNSManagedObjectContextを取得するための新しいルーチン

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

} 

機能を追加するための新しいエクササイズ

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

機能を追加するための

機能

以下、まずはルーチンと関係のない演習をいくつか作成します

「演習が作成されると、ルーチンのdoesntが存在し、それがその後に作成され、その名前が設定されている」

をして、いくつかの演習(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 
    } 

作成ルーチンを更新するユーザールーチンの結果を照会する関数です。ユーザールーティンは無しです。

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

あなたがそれを追加する演習を繰り返すまであなたと一緒にim /ルーチンにメイルを保存するルーチンを変更すると、その部分を実装するために、私はNSFetchedResultsControllerDelegateを使って、それを使ってnil演習を行うことは適切な方法であると仮定しますが、その方法はわかりません。また、演習配列を格納するためにコアデータエンティティに必要な属性のタイプは? – infernouk

+0

また、getUnmappedExerciseは、私のVCで非常に多くのエラーを引き起こします。これは、OPのコードとは対照的に、今のところ関数です。単純にそのコードを編集してタスクを実行することはできませんか? – infernouk

+0

私はあなたが実装部分だけを理解するためにその機能を追加しました。編集を参照してください.funcを削除しました。このコードを使用して、結果が表示されたら教えてください(Print文)。 –

0

name属性を使用する必要はありません。この属性は、UserRoutineの実際の名前を格納するために使用する必要があります。

コアデータ内のエンティティ間の関係は、エンティティの特定の属性に依存するのではなく、エンティティ自体の間にあります。

「私はルーチンビルダーが練習を見て、それに関係してnilを持つすべての演習をインポートしたい」だから...フェッチするフェッチ要求を作成します。関連するUserRoutineを持たないUserExerciseのすべてのエンティティ(つまり、userroutineはnilです)。

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

(無関連のルーチンで)UserExercisesの配列を取得するためにフェッチ要求、これを実行し

let orphanedExercises = managedObjectContext.executeFetchRequest(orphanedExerciseFetchRequest()) 

フェッチUserExercise設定し

"帰属演習とルーチンの作成" entitiyのプロパティーuserRoutineをルーチンに追加します(管理対象オブジェクトのコンテキストに変更を保存することを忘れないでください)。あなたが特定のルーチンの練習を取得したい場合は

myRoutine.userexercises = orphanedExercises 

その後、:

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

注:Xcodeで書かれていないので、いくつかのタイプミスなどがありますが、これが正しい方向にお手伝いします。 – Simo

+0

ありがとう、私は私の現在のフェッチ要求で私のOPを更新しました、これはこのコードを組み込むために変更することができますか、別の方法が必要ですか? – infernouk

+0

次の試みを試みましたが、致命的なエラーが出ましたか?怠惰なVaRのfetchedResultsControllerをfileprivate:NSFetchedResultsController = { せorphanedExerciseFetchRequest:NSFetchRequest = UserExercise.fetchRequest() orphanedExerciseFetchRequest.predicate = NSPredicate(形式: "userroutine ==ゼロ") せfetchedResultsController = NSFetchedResultsController(fetchRequest:orphanedExerciseFetchRequest 、managedObjectContext:self.persistentContainer.viewContext、sectionNameKeyPath:なし、キャッシュ名:なし) fetchedResultsController.delegate = self return fetchedResultsController}() – infernouk

関連する問題