Есть ли способ создать экземпляр NSManagedObject, не вставляя его? - PullRequest
54 голосов
/ 06 октября 2010

У меня есть пользовательский интерфейс для вставки транзакции.как только пользователь нажимает на плюс, он получает экран, и я хочу создать экземпляр своей сущности 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]

PS Я использую NSFetchedResultsController для этой таблицы, и я вижу, чтоNSFetchedResultsController вставляет секцию и объект в таблицу.

Я думаю, что если есть способ создать экземпляр транзакции NSManagedObject, я мог бы обновить его без сохранения, пока клиент не выберет.

Ответы [ 6 ]

37 голосов
/ 06 октября 2010

Несмотря на это, Маркус Зарра, похоже, продвигает контекстный подход nil, утверждая, что создавать новый контекст дорого.Подробнее см. этот ответ на аналогичный вопрос.

Обновление

В настоящее время я использую подход с нулевым контекстом и столкнулся с чем-тоэто может представлять интерес для других.Чтобы создать управляемый объект без контекста, вы используете метод initWithEntity:insertIntoManagedObjectContext: из NSManagedObject.Согласно документации Apple для этого метода:

Если context не nil, этот метод вызывает [context insertObject:self] (что вызывает awakeFromInsert).

Значение здесь важно.Использование контекста nil при создании управляемого объекта предотвратит вызов insertObject: и, следовательно, запретит вызов awakeFromInsert.Следовательно, любая инициализация объекта или установка значений свойств по умолчанию, выполняемая в awakeFromInsert, не будет выполняться автоматически при использовании nil контекста.

Итог: при использовании управляемого объекта без контекста, awakeFromInsert будетне вызываться автоматически, и вам может потребоваться дополнительный код для компенсации.

19 голосов
/ 06 октября 2010

вот как я с этим справился:

При загрузке, когда мы знаем, что имеем дело с новой транзакцией, я создал вне контекста одну.

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
    }
17 голосов
/ 06 октября 2010

Существует фундаментальная проблема с использованием нулевого MOC: объекты в разных MOC не должны ссылаться друг на друга & mdash; это предположительно также применимо, когда одна сторона отношений имеет ноль MOC. Что произойдет, если вы сохраните? (Что происходит, когда сохраняется другая часть вашего приложения?)

Если у вашего объекта нет отношений, вы можете сделать множество вещей (например, NSCoding).

Возможно, вы сможете использовать -[NSManagedObject isInserted] в NSPredicate (вероятно, это ДА между вставкой и успешным сохранением). Кроме того, вы можете использовать временное свойство с тем же поведением (установите значение YES в awakeFromInsert и NO в willSave). И то и другое может быть проблематичным, если другая часть вашего приложения сохраняет.

Использование второго MOC - вот как «предполагается» использовать CoreData; он обрабатывает обнаружение и разрешение конфликтов автоматически. Конечно, вы не хотите создавать новый MOC каждый раз, когда происходят изменения; может быть неопределенно разумно иметь один MOC для несохраненных изменений медленным «пользовательским потоком», если вы не возражаете против того, чтобы некоторые части пользовательского интерфейса видели несохраненные изменения в других частях (издержки связи между MOC незначительны). *

8 голосов
/ 06 октября 2010

Вы можете вставить NSManagedObjectContext с -[NSManagedObject initWithEntity:insertIntoManagedObjectContext:], передав nil для контекста управляемого объекта. Вы, конечно, должны присвоить его контексту (используя -[NSManageObjectContext insertObject:] перед сохранением. Однако, насколько я знаю, это не совсем намеченный шаблон в Базовых данных (но см. Ответ @ mzarra здесь * 1006). *). Есть некоторые хитрые проблемы с порядком (например, убедитесь, что экземпляр назначен контексту, прежде чем он ожидает его, и т. Д.). Более стандартный шаблон - создать новый контекст управляемого объекта и вставить в него новый объект. контекст. Когда пользователь сохраняет, сохраняет контекст и обрабатывает NSManagedObjectDidSaveNotification, чтобы объединить изменения с вашим «основным» контекстом. Если пользователь отменяет транзакцию, вы просто отбрасываете контекст и продолжаете свой бизнес.

2 голосов
/ 29 июня 2012

NSManagedObject может быть создан с использованием nil в качестве контекста, но если есть другие NSManagedObject, он должен ссылаться на него, что приведет к ошибке.Как я это делаю, я передаю контекст на экран назначения и создаю NSManagedObject на этом экране.Сделайте все изменения связать другие NSManagedObjects.Если пользователь нажимает кнопку отмены, я удаляю NSManagedObject и сохраняю контекст.Если пользователь нажимает кнопку «Сохранить», я обновляю данные в NSManagedObject, сохраняю их в контекст и освобождаю экран.На исходном экране я обновляю таблицу с перезагрузкой.

Удаление NSManagedObject на экране назначения дает основным данным время для обновления файла.Обычно этого времени достаточно, чтобы вы не увидели изменения в виде таблицы.В приложении iPhone Calendar у вас есть задержка от времени, которое оно экономит, до времени, которое оно отображается в виде таблицы.С точки зрения пользовательского интерфейса это можно считать хорошей вещью, когда ваш пользователь сосредоточится на только что добавленной строке.Надеюсь, это поможет.

0 голосов
/ 26 июня 2013
transaction = (Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:nil];

, если последний параметр равен нулю, он вернет NSManagedObject без сохранения в db

...