2013-04-28 3 views
2

나는 coreData에 저장하고 iOS dev을 사용하는 것에 대해 새로운 경험이있다.coredata에 일대 다 관계를 적절하게 저장하는 방법

내가 고유 식별자/idFB로 끌어왔다 내 DB에서 사용자를 가질 수 있도록하려면 해당 사용자 생성 및 루틴을 자신의 작업을 검색 할 수 있습니다 내가 달성하기 위해 노력하고 무엇

.

어디까지 갔습니까?

내가 제대로 잘 User와 연결된 Routine entity에서 routineName을 retriev 방법을 만들기 위해 (내 생각) 관리. fetch 방법을 참조하십시오.

내 문제 :

내가 올바른 엔티티 관계 협회 User (usersExercise) <--->> Routine (userID)에 저장하고 있지 않다 생각합니다. 순서대로 나는 내 save 방법이 옳지 않다라고 생각한다. 나는 전체 사용자를 userID로 저장하고 있고, 그 느낌이 옳지 않느냐? 주로 Routine.userID이 튀어 나오면 특정 ID 대신 관련 사용자 전체를 끌어 당깁니다. 나는 정말로 무엇을 기대 해야할지 모른다.

아무도 내가이 방법을 올바르게 만들 것을 도울 수 없습니까? 나는 coreData의 전체 과정을 저장하고 올바른 관계를 유지하는 데 매우 혼란 스럽다. 내가, [(사용자 *)이 일치 ("현재 결과 %에 @를 얻을"@ NSLog를 추가 할 때 또한

2013-04-28 22:33:26.555 iGym[7916:c07] result <User: 0xa480580> (entity: User; id: 0xa495a00 <x-coredata://D87CEBB4-016C-4A1B-802C-2D1117BB3E51/User/p1> ; data: { 
    dob = "1986-12-26 00:00:00 +0000"; 
    email = ".com"; 
    firstTime = nil; 
    gender = male; 
    height = nil; 
    idFB =3333; 
    idUserExternal = 0; 
    idUserInternal = 0; 
    isPT = nil; 
    language = "en_US"; 
    location = "London, United Kingdom"; 
    metricSystem = nil; 
    name = Joan; 
    nickname = nil; 
    password = nil; 
    surname = Thurft; 
    usersExercise = "<relationship fault: 0xa4824a0 'usersExercise'>"; 
    usersRoutine =  (
     "0xa495f00 <x-coredata://D87CEBB4-016C-4A1B-802C-2D1117BB3E51/Routine/p6>", 
     "0xa4877e0 <x-coredata://D87CEBB4-016C-4A1B-802C-2D1117BB3E51/Routine/p1>", 
     "0xa4877f0 <x-coredata://D87CEBB4-016C-4A1B-802C-2D1117BB3E51/Routine/p2>", 
     "0xa487800 <x-coredata://D87CEBB4-016C-4A1B-802C-2D1117BB3E51/Routine/p3>", 
     "0xa487810 <x-coredata://D87CEBB4-016C-4A1B-802C-2D1117BB3E51/Routine/p4>", 
     "0xa487820 <x-coredata://D87CEBB4-016C-4A1B-802C-2D1117BB3E51/Routine/p5>" 
    ); 
    weight = nil; 
}) 

:

- (void) save { 
    Routine *newRoutine = [NSEntityDescription insertNewObjectForEntityForName:@"Routine" inManagedObjectContext:context]; 

    newRoutine.users = [self getCurrentUser]; 
    newRoutine.routineName = @"myRoutine Test Name"; 
    NSError* error; 
    [context save:&error ]; 

    NSLog(@"Saved now try to fetch"); 
    [self fetch]; 

} 
-(void) fetch { 
    NSFetchRequest *fetchRequestItems = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entityItem = [NSEntityDescription entityForName:@"Routine" inManagedObjectContext:context]; 
    [fetchRequestItems setEntity:entityItem]; 
    User* user = [self getCurrentUser]; 
    // if i try [[self getCurrentUser] usersRoutine] it shows an error 

    [fetchRequestItems setPredicate:[NSPredicate predicateWithFormat:@"users == %@",user]]; 

    //Sort by last edit ordered 
    NSArray *sortDescriptors = [NSArray arrayWithObjects:nil]; 
    [fetchRequestItems setSortDescriptors:sortDescriptors]; 
    NSError *error = nil; 
    NSArray* Routines = [context executeFetchRequest:fetchRequestItems error:&error]; 
    NSLog(@"result %@", [(Routine *)Routines[0] users] ); 


} 
-(User *)getCurrentUser { 
    NSEntityDescription *entityDesc = [NSEntityDescription entityForName:@"User" inManagedObjectContext:context]; 
    NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
    [request setEntity:entityDesc]; 

    if (_appDelegate.isFB) 
    { 
     request.predicate = [NSPredicate predicateWithFormat:@"idFB LIKE %@",_appDelegate.fdID]; 
     NSError *error = nil; 
     NSArray *matches = [[context executeFetchRequest:request error:&error] mutableCopy]; 

     return (User *)matches[0]; 
    } else 
    { 
     NSLog(@"CreateRoutinePOPUP NON FB TO BE TESTED"); 
     request.predicate = [NSPredicate predicateWithFormat:@"email LIKE %@",_appDelegate.currentUser]; 
     NSError *error = nil; 
     NSArray *matches = [[context executeFetchRequest:request error:&error] mutableCopy]; 

     return (User *)matches[0]; 
    } 

enter image description here 페치에서 NSLog 인쇄하는 것입니다 [0] 사용자 루틴]); getCurrentUser 방법으로 I는 전체 사용자의 데이터를 얻을 수와의 관계는 당신이에 관계를 원하는 곳

usersExercise = "<relationship fault: 0xa464730 'usersExercise'>"; 
+0

다른 루프에서이 줄 : (사용자 *)는 일치 반환; 리턴해야하는지 (User *)는 [0]과 일치합니다; – user523234

답변

0

일대 다 객체에 "많은 객체"를 추가하려면 제공된 메소드를 사용해야합니다. 귀하의 경우에는이 addRoutineObject:

이 새로운 저장 방법을 시도라고 :

- (void) save { 

    Routine *newRoutine = [NSEntityDescription insertNewObjectForEntityForName:@"Routine" inManagedObjectContext:context]; 
    newRoutine.routineName = @"myRoutine Test Name"; 

    NSEntityDescription *entityDesc = [NSEntityDescription entityForName:@"User" inManagedObjectContext:context]; 
    NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
    [request setEntity:entityDesc]; 


    NSArray *matches; 
    NSError *error = nil; 
    if (_appDelegate.isFB) 
    { 
     request.predicate = [NSPredicate predicateWithFormat:@"idFB LIKE %@",_appDelegate.fdID]; 
     matches = [[context executeFetchRequest:request error:&error] mutableCopy]; 

    } else 
    { 
     NSLog(@"CreateRoutinePOPUP NON FB TO BE TESTED"); 
     request.predicate = [NSPredicate predicateWithFormat:@"email LIKE %@",_appDelegate.currentUser]; 
     matches = [[context executeFetchRequest:request error:&error] mutableCopy]; 
    } 

    if (matches.count == 0) 
    { 
     NSLog(@"no user matched"); 
    } 
    else 
    { 
     User *aUser = [matches objectAtIndex:0]; 
     [aUser addRoutineObject:newRoutine]; 
     if (![context save:&error]) 
     { 
      NSLog(@"couldn't save: %@", [error localizedDescription]); 
     } 
    } 
    } 
7

코어 데이터가 정확하게 당신이 다른 테이블에 userID 같은 일부 외국 키를 할당 표준 데이터베이스 작업처럼되지 않습니다 말한다 User 개체를 만든 다음 해당 외부 ID를 사용하여 exercise.where('user_id = ?', userID)과 같은 관계를 찾습니다. 대신 실제 관계를 정의하고 Core Data가 모든 결합 테이블 또는 외래 키 설정을위한 모든 장면을 처리하도록합니다. 대신 당신이 설정 한 방법

, 당신은 단지 User 개체에서이하려는 ExerciseRoutine 개체에 매핑 된 후 당신이 Exercise에 역 관계를 가질 것 exercisesroutines 두 관계 Routine은 불량 일 경우, users이라고합니다. 이제 usersExerciseexercises, usersRoutine, routines으로 바꾼 다음 ExerciseRoutine 엔티티의 경우 과 함께 userID을 바꿔야합니다.

실제로 역전 관계가 필요하지 않더라도 코어 데이터가 데이터 무결성을 위해 사용하므로 Xcode에서 불필요한 정보를 남겨두면 경고를 표시합니다.

이러한 관계를 설정하면 user.exercises과 같은 루틴이나 연습을 호출하여 해당 사용자에 대한 관련 연습 세트를 반환합니다. 당신이 주목 한대로, 코어 데이터는 해고 될 관계에 대해 fault이라고 부르는 것을 반환하고 실제로 그 관계의 내용이 필요할 때 데이터를 반환합니다. 오류가 있으므로 데이터 세트에서 불필요한 쿼리를 실행하는 대신 필요한 정보 만 정확하게 반환됩니다.

또 다른 중요한 점은 코어 데이터가 고유 ID를 userID과 같이 참조하지 않는다는 것입니다. 대신 Core Data 내의 각 객체에는 [objectName objectID] (데이터 저장소에 저장 한 후에 만 ​​영구적 인 ID)이 있습니다. 특수한 경우를 제외하고 엔티티의 속성으로 고유 한 ID를 설정하지 않아도됩니다.

objectID도 마찬가지입니다. 백그라운드 처리를 위해 멀티 스레드 응용 프로그램처럼 객체를 전달하지 않는 한 NSManagedObjectID은 스레드로부터 안전하며이 스레드를 사용하여 백그라운드 스레드/관리 객체 컨텍스트에서 객체를 다시 찾습니다.

정말 그것은 당신이 일반 데이터베이스 설정/아키텍처를 사용하는 경우 첫 번째 코어 데이터로 변환에서 좀 이상 할 수 있습니다와 같은 http://www.raywenderlich.com/934/core-data-on-ios-5-tutorial-getting-started

코어 데이터에 좋은 소개를 읽어 보시기 바랍니다,하지만 한 번 것

실제로 익숙해지면 훨씬 빨라지고 배후의 모든 어려운 작업을 처리 할 수 ​​있습니다. 코멘트에서


업데이트 :

당신은 코어 데이터에서 관계의 개념을 오해하고 있습니다. 핵심 데이터에서 관계는 일반적인 데이터베이스 조인 관계처럼 연관된 ID를 반환하지 않습니다. 대신, 그것은 관계에서 데이터가 필요할 때 해고되는 오류를 리턴합니다. 그래서 당신은 절약 할 때 그것이 있어야처럼 전체 User 개체를 반환하지,하지만 해고 조회됩니다 관련 User 객체에 fault 당신이 exercise.user.name

귀하의 코드가 정확히 작동하고 뭔가를 할 때, 당신은 단지입니다 잘못된 가정하에 그것은 그렇지 않습니다.

+0

설명해 주셔서 감사합니다! :) ... 나는 CD가 오류나 경고를 던지지 않기 때문에 관계 정체성을 올바르게 설정했다고 생각합니다. 그래서 제가 맞다면 제가 CD 그래픽에서 만든 협회가 틀렸다는 말을하는 겁니까? 저에게 해결책이 될 수 있다고 생각합니까? 감사합니다. –

+0

예, 일반적인 데이터베이스 조인 관계를 설정하는 방법이지만 핵심 데이터에서 관계를 설정하는 방법은 아닙니다. 대신에,'exercises','usersRoutine'을'routines'로 바꾸고,'userID'를'exercises'와'Routine' 엔티티를'users'로 대체 할 필요가 있습니다. – iwasrobbed

+0

나는 'has-and-belong-to-many' 관계라고 가정하고 있습니다. 그래서 그러한 옵션들이 그 관계에 대한 Core Data 메뉴에서 선택되었는지 확인하십시오. – iwasrobbed

관련 문제