2013-05-02 2 views
3

거의 동일한 제목의 이전 질문과 동일한 문제가 아니기 때문에 다음 단계를 밟았습니다.Magical Record import (다음 단계)

나는 Person 엔티티가 있습니다.

Person 
-------- 
name  - mappedKeyName: FullName 
email  - mappedKeyName: EmailAddress 
personID - mappedKeyName: Id 
-------- 
photos 

그리고 Photo 엔티티.

Photo 
-------- 
image 
createDate - mappedKeyName: Date 
photoID - mappedKeyName: Id 
-------- 
owner (type Person) - mappedKeyName: UserId - relatedByAttribute: personID 

너무 Person에 관련된 다른 개체가 있고 이들에 대한 JSON 내 설정 가져 오기와 함께 작동이 JSON으로 ... 그래서

{ 
    ObjectId : blah, 
    Owner : { 
     Id : 12345asdfg, 
     FullName : Oliver, 
     EmailAddress : [email protected] 
    } 
} 

온다. 존재하지 않는 사람 기록 (Id 포함)이 생성됩니다. 그리고 존재하는 것은 업데이트됩니다.

그러나, 사진 JSON 객체는 객체가 같은 내려와 때 그 사람의 수입에 도달 할 때 마법 기록 가져 오기가 중지 ...

{ 
    Id : thisIsThePhotoID, 
    Date : today, 
    UserId : 12345asdfg 
} 

과 같이 제공됩니다. 코드는에 충돌

...

- (id) MR_relatedValueForRelationship:(NSRelationshipDescription *)relationshipInfo 
{ 
    NSString *lookupKey = [self MR_lookupKeyForRelationship:relationshipInfo]; 
    return lookupKey ? [self valueForKeyPath:lookupKey] : nil; // it stops here. 
} 

lookupKey의 값은 @ "personID". 브레이크 포인트가 제공에서 relationshipInfo을 인쇄

...

$6 = 0x1fd695e0 (<NSRelationshipDescription: 0x1fd695e0>), 
    name owner, 
    isOptional 0, 
    isTransient 0, 
    entity Photo, 
    renamingIdentifier owner, 
    validation predicates(), 
    warnings(), 
    versionHashModifier (null) 
    userInfo { 
     mappedKeyName = UserId; 
     relatedByAttribute = personID; 
    }, 
    destination entity Person, 
    inverseRelationship photos, 
    minCount 1, 
    maxCount 1, 
    isOrdered 0, 
    deleteRule 1 

난 정말이 작동하지 않는 이유를 모르겠어요. 나는 현명 오류를보고하지 않습니다.

답변

17

MagicalRecord이 JSON 형식으로 자동으로 관계를 맵핑 할 수

MagicalRecord 예를 들면, 물론 JSON에서 객체가되도록 Person 객체 관계, 그 것이다 매핑하기 위해서는
{ 
    Id : thisIsThePhotoID, 
    Date : today, 
    UserId : 12345asdfg 
} 

:

{ 
    Id : thisIsThePhotoID, 
    Date : today, 
    User : { 
     UserId : 12345asdfg 
    } 
} 

이 방법 MagicalRecord는 객체이고 그 위의 ID와 Person 레코드를 기존 데이터베이스에서 적절한 조회를하고 관계를 매핑합니다 알고있다.

이렇게 두 가지 문제가 있습니다. JSON 출력을 변경할 수 없다면 수동으로 직접 관계를 매핑하는 Photo에 카테고리 클래스를 만들어야합니다. 나는 두 번째 문제 이후에 그것을 얻을 것이다.

위의 JSON 형식은 이미 사용자를 구문 분석하고 데이터베이스에 레코드를 저장했다고 가정합니다. MagicalRecord가 없으면 위의 ID를 가진 새로운 Person 레코드를 만들지 만 그 개체에는 다른 속성이 없으므로 (UserId 키가 사전의 유일한 속성임을 알 수 있음) 상당히 비어있을 것이며 이름과 전자 메일을 포함하지 않습니다 주소.당신은 항상 당신의 JSON을 연장 할 수 있습니다 (그 가능성이있는 경우) 사진 사전 내부의 이러한 속성뿐만 아니라에서 사람이 사전을 포함 :

json으로 페이로드는 매우 작다는 그래서 그렇게 다치게하지 않습니다되어
{ 
    Id : thisIsThePhotoID, 
    Date : today, 
    User : { 
     UserId : 12345asdfg, 
     FullName : Oliver, 
     EmailAddress : [email protected] 
    } 
} 

가능하다면. 또한 데이터베이스에 이미 존재하지 않는 경우 새로운 Person 레코드 만 생성합니다.

그런 다음 수동 매핑. 위의 형식으로 JSON을 변경할 수없는 경우 수동으로 관계 매핑을 재정의해야합니다. JSON이 MagicalRecord가 매핑하는 방식으로 준비되지 않았기 때문입니다.

Photo+Mapping.h/.m이라는 Photo에 대한 범주 클래스를 만듭니다. 나는 이것을 위해 +Mapping을 고집하고 싶다. 그런 다음 클래스는 헤더와 구현 파일에 Photo (Mapping)이어야하며 잘하겠습니다. 그들과 import<;attributeName>;:import<;relationshipName>;:이다 사이

MagicalRecord는 무시할 인스턴스 가능한 다수의 방법 (MagicalRecord 작성자에 의해 작성된 this article on MagicalRecord importing 후반부 참조)을 갖는다. 또한 매핑 자체를 재정의 할 수있는 클래스 자체에는 willImport:, didImport:shouldImport: 메쏘드가 있습니다.

귀하의 경우에는 import<;relationshipName>;: 또는 shouldImport:을 사용할 수 있습니다. 나는 당신이 이미 당신의 모든 Person 객체들을 매핑했는지에 따라 약간의 이점을 가지고 있고 Photo 객체상의 관계 매핑을 위해 사용할 수 있기 때문에 나는이 두가지를 취했습니다.

다음은 할 수있는 일의 예입니다. 원할 경우 몇 가지를 조합하여 선택할 수도 있습니다. 그렇게 할 수도 있습니다. 여기에 메모 : 항상NSManagedObjectContext을 사용하여 매핑을 무시할 때 (MagicalRecord를 통해 쉽게 액세스 할 수 있습니다. self.managedObjectContext) 그렇지 않으면 문맥 문제가 발생합니다. 이 도움이

#import "Photo+Mapping.h" 
#import "Person.h" 

// Assuming you only want to import the Photo object if you already have a Person stored this is a great method to tell MagicalRecord whether to continue with importing or not 
-(BOOL)shouldImport:(id)data { 
    Person *person = [Person findFirstByAttribute:data[@"UserId"] value:@"personID" inContext:self.managedObjectContext]; 
    if (!person) { 
     // no Person object exists so don't import the Photo object - again this is up to you since you might want to create the record if not 
     return NO; 
    } 
    // you can set the relationship here (you might as well) or use the importPerson: method below (doing a second lookup, which is unnecessary at this point) 
    [self setPerson:person]; 
    return YES; 
} 

// If you use this method you're doing the lookup to check whether a record exist when MagicalRecord is trying to map the Person relationship 
-(void)importPerson:(id)data { 
    Person *person = [Person findFirstByAttribute:data[@"UserId"] value:@"personID" inContext:self.managedObjectContext]; 
    if (!person) { 
     // if no Person record exists for the associated UserId, you should create one (or not - if you choose not to, it's wise to throw away this Photo object) 
     person = [Person createInContext:self.managedObjectContext]; 
     [person setPersonID:data[@"UserId"]]; 
    } 
    // set the relationship 
    [self setPerson:person]; 
} 

// finally you can also use the following method when MagicalRecord is done mapping and get rid of the Photo object if the Person relationship is nil: 
-(void)didImport:(id)data { 
    if (!self.person) { 
     [self deleteInContext:self.managedObjectContext]; 
    } 
} 

희망 :

하는 사람을 가져주세요! 궁금한 점이 있으면 알려주세요.

+0

우수 답변! 매우 감사합니다. 가져 오기가이 형식으로 작동하지 않는다고 말하는 사람이 가장 먼저 나옵니다. (이전의 세 가지 질문은 모두 "처음 일하는 것"이라고 대답했습니다.) 내일 다시 돌아와서 솔루션을 구현하려고합니다. 다시 한번 감사드립니다. – Fogmeister

+0

@ Fogmeister 내가 어떻게 도움이되는지 궁금한 점이 있으면 알려주십시오. – runmad

+0

@ Fogmeister 문제를 해결하는 데 도움이되었는지 궁금합니다. – runmad

관련 문제