programing

삽입하지 않고 NSManagedObject를 인스턴스화하는 방법이 있습니까?

minecode 2021. 1. 15. 07:59
반응형

삽입하지 않고 NSManagedObject를 인스턴스화하는 방법이 있습니까?


트랜잭션을 삽입하는 사용자 인터페이스가 있습니다. 사용자가 플러스를 클릭하면 화면이 표시되고 Core Data NSManagedObject 엔티티를 인스턴스화하여 사용자가 작업 할 수 있도록합니다. 그런 다음 사용자가 저장 버튼을 클릭하면 저장 기능을 호출합니다.

그래서 아래로 코드 :

transaction = (Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:self.managedObjectContext];
//even if i dont call save: its going to show up on my table
[self.managedObjectContext save:&error]

추신 나는 해당 테이블에서 NSFetchedResultsController를 사용하고 있으며 NSFetchedResultsController가 섹션과 개체를 테이블에 삽입하고 있음을 알 수 있습니다.

내 생각은 트랜잭션 NSManagedObject를 인스턴스화하는 방법이 있다면 클라이언트가 선택할 때까지 저장하지 않고 업데이트 할 수 있다는 것입니다.


nil MOC를 사용하는 데는 근본적인 문제가 있습니다. 서로 다른 MOC의 객체는 서로를 참조하도록되어 있지 않습니다. 이것은 아마도 관계의 한쪽에 nil MOC가있을 때도 적용됩니다. 저장하면 어떻게 되나요? (앱의 다른 부분이 저장되면 어떻게 되나요?)

객체에 관계가 없으면 할 수있는 일이 많이 있습니다 (예 : NSCoding).

-[NSManagedObject isInserted]NSPredicate 에서 사용할 수 있습니다 (아마도 삽입하고 성공적으로 저장하는 사이에 YES). 또는 동일한 동작으로 임시 속성을 사용할 수 있습니다 (awakeFromInsert에서 YES로 설정하고 willSave에서 NO로 설정). 앱의 다른 부분이 저장되면이 두 가지 모두 문제가 될 수 있습니다.

두 번째 MOC를 사용하는 것은 CoreData가 사용되는 방법입니다. 자동으로 충돌 감지 및 해결을 처리합니다. 물론 변경 사항이있을 때마다 새로운 MOC를 생성하고 싶지는 않습니다. UI의 일부 부분이 다른 부분에서 저장되지 않은 변경 사항을 보는 것을 신경 쓰지 않는다면 느린 "사용자 스레드"에 의한 저장되지 않은 변경 사항에 대해 하나의 MOC를 갖는 것이 모호 할 수 있습니다 (MOC 간 통신의 오버 헤드는 무시할 수 있음).


가치가있는만큼 Marcus Zarra nil는 새로운 컨텍스트를 만드는 데 비용이 많이 든다고 주장하면서 컨텍스트 접근 방식을 홍보하는 것 같습니다 . 자세한 내용 은 유사한 질문에 대한 이 답변참조하십시오 .

최신 정보

나는 현재 nil 컨텍스트 접근 방식을 사용하고 있으며 다른 사람들이 관심을 가질만한 것을 발견했습니다. 컨텍스트없이 관리되는 개체를 만들려면의 initWithEntity:insertIntoManagedObjectContext:메서드 를 사용합니다 NSManagedObject. 이 방법에 대한 Apple의 문서에 따르면 :

하면 context되지 nil,이 메소드가 호출하는 [context insertObject:self](원인 awakeFromInsert호출 할 수 있습니다).

여기서 의미는 중요합니다. nil관리되는 개체를 만들 때 컨텍스트를 사용하면 insertObject:호출되지 않으므로 호출되지 awakeFromInsert않습니다. 따라서에서 수행 된 개체 초기화 또는 기본 속성 값 설정은 컨텍스트를 awakeFromInsert사용할 때 자동으로 발생하지 않습니다 nil.

결론 : 컨텍스트없이 관리되는 개체를 사용할 때 awakeFromInsert자동으로 호출되지 않으며이를 보완하기 위해 추가 코드가 필요할 수 있습니다.


내가 어떻게 해결했는지는 다음과 같습니다.

로드시, 우리가 새로운 트랜잭션을 처리하고 있다는 것을 알고있는 상황에서 나는 컨텍스트를 벗어난 트랜잭션을 생성했습니다.

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Transaction" inManagedObjectContext:self.managedObjectContext];
        transaction = (Transaction *)[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];

그런 다음 관계 선을 설정할 때 이렇게했습니다.

if( transaction.managedObjectContext == nil){
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Category" inManagedObjectContext:self.managedObjectContext];
        Category *category = (Category *)[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
        category.title = ((Category *)obj).title;
        transaction.category = category;
        [category release];
    }
    else {
        transaction.category = (Category *)obj;
    }

그리고 마지막에 저장 :

if (transaction.managedObjectContext == nil) {
        [self.managedObjectContext insertObject:transaction.category];
        [self.managedObjectContext insertObject:transaction];
    }
    //NSLog(@"\n saving transaction\n%@", self.transaction);

    NSError *error;
    if (![self.managedObjectContext save:&error]) {
        // Update to handle the error appropriately.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    }

You can insert an NSManagedObjectContext with the -[NSManagedObject initWithEntity:insertIntoManagedObjectContext:], passing nil for the managed object context. You must, of course, assign it to a context (using -[NSManageObjectContext insertObject:] before saving. This is, as far as I know, not really the intended pattern in Core Data, however (but see @mzarra's answer here). There are some tricky ordering issues (i.e. making sure the instance gets assigned to a context before it expects to have one, etc.). The more standard pattern is to create a new managed object context and insert your new object into that context. When the user saves, save the context, and handle the NSManagedObjectDidSaveNotification to merge the changes into your 'main' context. If the user cancels the transaction, you just blow away the context and go on with your business.


An NSManagedObject can be created using the nil as the context, but if there other NSManagedObjects it must link to it will result in an error. The way I do it I pass the context into the destination screen and create a NSManagedObject in that screen. Make all the changes link other NSManagedObjects. If the user taps the cancel button I delete the NSManagedObject and save the context. If the user taps the the save button I update the data in the NSManagedObject, save it to the context, and release the screen. In the source screen I update the table with a reload.

Deleting the NSManagedObject in the destination screen gives core data time to update the file. This is usually enough time for you not to see the change in the tableview. In the iPhone Calendar app you have a delay from the time it saves to the time it shows up in the tableview. This could be considered a good thing from a UI stand point that your user will focus on the row that was just added. I hope this helps.


transaction = (Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:nil];

if the last param is nil, it will return a NSManagedObject without save to db

ReferenceURL : https://stackoverflow.com/questions/3868514/is-there-a-way-to-instantiate-a-nsmanagedobject-without-inserting-it

반응형