development

임시 NSManagedObject 인스턴스를 처리하는 방법은 무엇입니까?

big-blog 2020. 9. 15. 18:51
반응형

임시 NSManagedObject 인스턴스를 처리하는 방법은 무엇입니까?


NSManagedObject인스턴스 를 만들고 몇 가지 작업을 수행 한 다음이를 폐기하거나 sqlite db에 저장해야합니다. 문제는 NSManagedObject연결되지 않은 인스턴스를 만들 수 없다는 NSManagedObjectContext것입니다. 즉, DB에있는 일부 개체가 필요하지 않다고 결정한 후 어떻게 든 정리해야합니다.

이를 처리하기 위해 동일한 코디네이터를 사용하여 메모리 내 저장소를 만들고 assignObject:toPersistentStore.Now 를 사용하여 임시 개체를 배치 하고 있습니다. 이러한 임시 개체가 데이터에 도달하지 않도록하려면 어떻게해야하나요? 두 상점 컨텍스트에 공통입니까? 아니면 그러한 작업에 대해 별도의 컨텍스트를 만들어야합니까?


UPD :

이제 메모리 내 저장소에 대해 별도의 컨텍스트를 만드는 방법을 생각하고 있습니다. 한 컨텍스트에서 다른 컨텍스트로 개체를 어떻게 이동합니까? [context insertObject :]를 사용하고 있습니까? 이 설정에서 제대로 작동합니까? 객체 그래프에서 하나의 객체를 삽입하면 전체 그래프도 컨텍스트에 삽입됩니까?


참고 : 이 답변은 매우 오래되었습니다. 전체 기록을 보려면 댓글을 참조하세요. 이후 권장 사항이 변경되어 더 이상 연결되지 않은 NSManagedObject인스턴스를 사용하지 않는 것이 좋습니다 . 현재 권장 사항은 임시 자식 NSManagedObjectContext인스턴스 를 사용하는 것 입니다.

원래 답변

이를 수행하는 가장 쉬운 방법 NSManagedObject은 연결된 NSManagedObjectContext.

NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:myMOC];
NSManagedObject *unassociatedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];

그런 다음 저장하려는 경우 :

[myMOC insertObject:unassociatedObject];
NSError *error = nil;
if (![myMoc save:&error]) {
  //Respond to the error
}

iOS5는 Mike Weller의 대답에 대한 더 간단한 대안을 제공합니다. 대신 자식 NSManagedObjectContext를 사용하십시오 . NSNotificationCenter를 통해 트램폴린이 필요하지 않습니다.

하위 컨텍스트를 만들려면 :

NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
childContext.parentContext = myMangedObjectContext;

그런 다음 자식 컨텍스트를 사용하여 개체를 만듭니다.

NSManagedObject *o = [NSEntityDescription insertNewObjectForEntityForName:@"MyObject" inManagedObjectContext:childContext];

변경 사항은 하위 컨텍스트가 저장 될 때만 적용됩니다. 따라서 변경 사항을 취소하려면 저장하지 마십시오.

관계에는 여전히 제한이 있습니다. 즉, 다른 컨텍스트의 개체에 대한 관계를 만들 수 없습니다. 이 문제를 해결하려면 objectID를 사용하여 자식 컨텍스트에서 개체를 가져옵니다. 예.

NSManagedObjectID *mid = [myManagedObject objectID];
MyManagedObject *mySafeManagedObject = [childContext objectWithID:mid];
object.relationship=mySafeManagedObject;

하위 컨텍스트를 저장하면 변경 사항이 상위 컨텍스트에 적용됩니다. 상위 컨텍스트를 저장하면 변경 사항이 유지됩니다.

자세한 설명 wwdc 2012 세션 214참조하십시오 .


이러한 종류의 작업을 수행하는 올바른 방법은 새로운 관리 개체 컨텍스트를 사용하는 것입니다. 동일한 영구 저장소를 사용하여 관리되는 개체 컨텍스트를 만듭니다.

NSManagedObjectContext *tempContext = [[[NSManagedObjectContext alloc] init] autorelease];
[tempContext setPersistentStore:[originalContext persistentStore]];

그런 다음 새 개체를 추가하고 변경합니다.

저장할 때가되면 tempContext에서 [tempContext save : ...]를 호출하고 저장 알림을 처리하여 원래 컨텍스트에 병합해야합니다. 객체를 버리려면이 임시 컨텍스트를 해제하고 잊어 버리십시오.

따라서 임시 컨텍스트를 저장하면 변경 사항이 저장소에 유지되며 해당 변경 사항을 기본 컨텍스트로 다시 가져 오면됩니다.

/* Called when the temp context is saved */
- (void)tempContextSaved:(NSNotification *)notification {
    /* Merge the changes into the original managed object context */
    [originalContext mergeChangesFromContextDidSaveNotification:notification];
}

// Here's where we do the save itself

// Add the notification handler
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(tempContextSaved:)
                                             name:NSManagedObjectContextDidSaveNotification
                                           object:tempContext];

// Save
[tempContext save:NULL];
// Remove the handler again
[[NSNotificationCenter defaultCenter] removeObserver:self
                                                name:NSManagedObjectContextDidSaveNotification
                                              object:tempContext];

이것은 멀티 스레드 코어 데이터 작업을 처리하는 방법이기도합니다. 스레드 당 하나의 컨텍스트.

관계를 추가하기 위해이 임시 컨텍스트에서 기존 객체에 액세스해야하는 경우 객체의 ID를 사용하여 다음과 같은 새 인스턴스를 가져와야합니다.

NSManagedObject *objectInOriginalContext = ...;
NSManagedObject *objectInTemporaryContext = [tempContext objectWithID:[objectInOriginalContext objectID]];

If you try to use an NSManagedObject in the wrong context you will get exceptions while saving.


Creating temporary objects from nil context works fine until you actually try to have a relationship with an object whose context != nil!

make sure your okay with that.


What you are describing is exactly what an NSManagedObjectContextis for.

From Core Data Programming Guide: Core Data Basics

You can think of a managed object context as an intelligent scratch pad. When you fetch objects from a persistent store, you bring temporary copies onto the scratch pad where they form an object graph (or a collection of object graphs). You can then modify those objects however you like. Unless you actually save those changes, however, the persistent store remains unaltered.

And Core Data Programming Guide: Managed Object Validation

This also underpins the idea of a managed object context representing a "scratch pad"—in general you can bring managed objects onto the scratch pad and edit them however you wish before ultimately either committing the changes or discarding them.

NSManagedObjectContexts are designed to be lightweight. You can create and discard them at will - it's the persistent stores coordinator and it's dependancies that are "heavy". A single persistent store coordinator can have many contexts associated with it. Under the older, obsolete thread confinement model this would mean setting the same persistent store coordinator on each context. Today it would mean connecting nested contexts to a root context that is associated with the persistent store coordinator.

Create a context, create and modify managed objects within that context. If you want to persist them and communicate those changes, save the context. Otherwise discard it.

Attempting to create managed objects independent of an NSManagedObjectContext is asking for trouble. Remember that Core Data is ultimately a change tracking mechanism for an object graph. Because of this, managed objects are really part of the managed object context. The context observes their life cycle, and without the context not all of the managed object functionality will work correctly.


Depending on your use of the temporary object there are some caveats to the above recommendations. My use case is that I want to create a temporary object and bind it to views. When the user opts to save this object, I want to setup relationships to existing object(s) and save. I want to do this to avoid creating a temporary object to hold those values. (Yes, I could just wait until the user saves and then grab the view contents but I'm putting these views inside of a table and the logic to do this is less elegant.)

The options for temporary objects are:

1) (Preferred) Create the temporary object in a child context. This won't work because I'm binding the object to the UI and I can't guarantee the object accessors are called on the child context. (I have found no documentation that states otherwise so I have to assume.)

2) Create the temporary object with nil object context. This doesn't work and results in data loss/corruption.

My Solution: I solved this by creating the temporary object with nil object context but when I save the object, rather than inserting it as #2, I copy all of it's attributes into a new object that I create in the main context. I created a supporting method in my NSManagedObject subclass called cloneInto: that lets me copy attributes and relationships easily for any object.


For me Marcus's answer didn't work. Here's what worked for me:

NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:myMOC];
NSManagedObject *unassociatedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];

then, if I decide to save it:

[myMOC insertObject:unassociatedObjet];
NSError *error = nil;
[myMoc save:&error];
//Check the error!

We must also not forget to release it

[unassociatedObject release]

I am rewriting this answer for Swift as all similar questions for swift redirect to this question.

You can declare the object without any ManagedContext using the following code.

let entity = NSEntityDescription.entity(forEntityName: "EntityName", in: myContext)
let unassociatedObject = NSManagedObject.init(entity: entity!, insertInto: nil)

Later on, to save the object you can insert it into the context and save it.

myContext.insert(unassociatedObject)
// Saving the object
do {
    try self.stack.saveContext()
    } catch {
        print("save unsuccessful")
    }
}

참고URL : https://stackoverflow.com/questions/3256195/how-to-deal-with-temporary-nsmanagedobject-instances

반응형