2009-10-12 2 views
35

Apple의 CoreDataBooks 샘플 응용 프로그램을 바탕으로 보조 관리 대상 개체 컨텍스트로 데이터를 가져 와서 기본 관리 개체에 병합하기위한 기초로 사용하고 있습니다. 문맥.다른 컨텍스트의 개체 사이에 'xyz'관계 설정 시도가 잘못되었습니다.

내가 가져 오는 데이터는 Owner 엔티티 ("소유자")와 일대일 관계가있는 Book 엔티티입니다. Owner 엔티티는 Book ("books"라고 함)과 다 대다 관계입니다. Book N 통해

<Owner> 
    <Name>alexpreynolds</Name> 
    <ID>123456</ID> 
</Owner> 
<Books> 
    <Book>Book One</Book> 
    <Book>Book Two</Book> 
    ... 
    <Book>Book N</Book> 
</Books> 

Book One 하나 Owner ("alexpreynolds, 123456")와 연관되어

내 데이터는 XML 형식의 문서이다.

Owner 인스턴스와 Book 인스턴스로 구성된 NSMutableSet 인스턴스로 구문 분석하고 있습니다.

처음 저장하려고하면 잘 저장되고 병합 된 데이터가 테이블보기에 나타납니다.

그러나 두 번째 저장시 XML 내용에 새 책이 포함되어 있으면 작동하지 않습니다.

여기 무슨 일이야 :

그때 새로운 Book를 포함하는 XML 문서를로드하지 이미 기본 관리 개체 컨텍스트한다. 새로운 Book은 다른 Book과 연결된 것과 동일한 Owner을 사용하고 있습니다.

나는 (나는 이미 내 기본 관리 개체 컨텍스트에있는)이 독특한 Owner 관리되는 개체를 골라 루틴 및 기본 MOC에서 발견 하지있는 독특한 Book 있습니다.

여기에서 보조 MOC에 새로운 Book 개체를 만들고 주체 MOC에서 찾은 고유 Owner을 가리 키도록 해당 "owner"관계를 설정했습니다. 나는 아직도 차에서 기존 Owner와 연결할 수 있도록 내가, 보조 MOC에서 새로운 Book 개체를 만들려면 어떻게해야합니까

*** Terminating app due to uncaught 
exception 'NSInvalidArgumentException', 
reason: 'Illegal attempt to establish a 
relationship 'owner' between objects in 
different contexts 

(source = <Book: 0x7803590> 
(entity: Book; id: 0x7802ae0 <x-coredata:/// 
Book/t527F06B2-3EB5-47CF-9A29-985B0D3758862> 
; data: { 
creationDate = 2009-10-12 06:01:53 -0700; 
name = nil; 
nameInitial = nil; 
operations = (
); 
owner = nil; 
type = 0; 
}) , 

destination = <Owner: 0x78020a0> (entity: 
Owner; id: 0x3a56f80 <x-coredata://043AF2F0-1AD0- 
4078-A5E8-E9D7071D67D1/Owner/p1> ; data: { 
books = "<relationship fault: 0x7801bf0 'books'>"; 
displayName = alexpreynolds; 
ownerID = 123456; 
}))' 

: 내가 저장하면

, 나는 다음과 같은 오류가 MOC?

답변

63

다른 관리 객체 컨텍스트의 객체 간에는 관계를 설정할 수 없습니다. 따라서이를 해결하는 한 가지 방법은 객체를 관리 객체 컨텍스트에 가져 오는 것입니다.예를 들어

:

실제로 owner와 같은 관리되는 개체 컨텍스트에 Book를 가져 오는되는 일을하는지 그래서
NSManagedObject *book = // get a book in one MOC 
NSManagedObject *owner = // get an owner in a different MOC 
[[owner mutableSetValueForKey:@"books"] addObject:[owner.managedObjectContext objectWithID:[book objectID]]]; 

. 하지만 book이 이미 저장되어있는 경우에만 가능하다는 점에 유의하십시오. 관리 객체 컨텍스트는 영구 저장소에서 객체를 찾을 것이므로 먼저 저장해야합니다.

+0

감사합니다. 백그라운드 GCD 스레드에서 코어 데이터로 작업하고 있었기 때문에 백그라운드 NSManagedObject를 가지고 있어야만했습니다. 메인 객체 인 NSManagedObject를 사용하여 부모 객체를 삽입하는 것을 잊어 버렸습니다! 어쨌든 감사합니다! :) – runmad

1

오류 메시지에 따르면 값이 다른 컨텍스트에있는 다른 개체로 설정된 한 개의 핵심 데이터 개체에는 관계가 허용되지 않습니다. 이 문제를 해결할 수있는 한 가지 방법은 새 개체를 저장하고 기본 컨텍스트로 다시 병합 한 다음에 owner 관계를 적절하게 설정하기 전까지 기다리는 것입니다 (두 개체가 모두 동일한 컨텍스트에 있으므로 아무 문제가 없음) .

+0

핵심 데이터 북 예제 다음에 병합이 발생한 후에 보조 MOC가 해제됩니다. 보조 MOC를 대신 인스턴스 변수로 만들면 기본 MOC의 소유자가 보조 MOC의 책을 참조하여 오류 메시지를 표시합니다. 보조 MOC 소유자가 보조 MOC에있는 책을 참조하는 경우 병합 할 때 중복 소유자 인스턴스가 생겨서 올바르지 않습니다. 이상적으로는 기존 소유자와 연결할 수 있습니다. 시간이 있으시면 좀 더 자세히 설명해 주시겠습니까? –

8

동일한 문제가 있었는데이 문장을 통해 오류를 해결하는 데 도움이되었습니다. 여기에 내 코드의

You can't have relationships between objects in different managed object contexts. So one way of getting around that is to bring the object into the managed object context.

(나는 당신을 위해 작동하도록 변수를 대체) :

// Have the owner object and get the managedObjectContext 
Owner *owner = [[DataFunctions alloc] getCurrentOwner]; 
NSManagedObjectContext *context = [owner managedObjectContext]; 

// Create a book and use the manageObjectContext of owner 
Book *book = [NSEntityDescription insertNewObjectForEntityForName:@"Book" inManagedObjectContext:context]; 
[newQuote setValue: "Book Title" forKey:@"title"]; 
[newQuote setOwner:owner]; 

을 나는이 도움이 :)

0
book *book = [mainContext ........] //Get book from default context 

NSManagedObjectID *objectId = [book objectID]; 

Book *tmpBook = [tmpContext objectWithID:objectId]; //Now book has the legal relationship 
3

을 여기에 희망을, 당신은 설정하려는 다른 문맥으로 페치/생성되는 2 개의 객체 간의 관계. 핵심 데이터는 그러한 관계를 수립하는 것을 허용하지 않습니다. 이를 달성하려면 objectID를 사용하여 첫 번째 객체의 컨텍스트에서 두 번째 객체 (관계를 만들려고합니다)를 가져와야합니다. 이제이 두 객체 사이의 관계를 설정할 수 있어야합니다. 예 :

MagicalRecord.saveWithBlock({[unowned self] (localContext: NSManagedObjectContext!) in 

    let user = User.MR_createEntityInContext(localContext)! 
    ..... 
    ..... 
}) //here local context stores data on end of block itself 

MagicalRecord.saveWithBlock({[unowned self] (localContext: NSManagedObjectContext!) in 

    let address = Address.MR_createEntityInContext(localContext)! 
    ..... 
    ..... 
    let user = localContext.objectWithID(self.user!.objectID) as! User 
    user.address = address 
}) 

희망이 도움이 될 것입니다!

관련 문제