Нужна помощь в понимании ошибок в Core Data - PullRequest
2 голосов
/ 21 сентября 2011

У меня есть объект Core Data, который использует пользовательский подкласс NSManagedObject. У меня есть несколько переменных экземпляра и свойств, которые не связаны с атрибутами или связями Core Data. Пример того, что я делаю, это:

@interface Root : NSManagedObject
{
    Foo *foo;
    Bar *bar;
}

@property (nonatomic, retain) Foo *foo;
@property (nonatomic, retain) Bar *bar;

// Core Data generated
@property (nonatomic, retain) Node *relationship;
@property (nonatomic, retain) NSString *attribute;

-(void)awake;

@end


@implementation Root

@synthesize foo;
@synthesize bar;

@dynamic relationship;
@dynamic attribute;

-(void)awakeFromInsert {
    [super awakeFromInsert];
    [self awake];
}

-(void)awakeFromFetch {
    [super awakeFromFetch];
    [self awake];
}

-(void)awake {
    Foo *newFoo = [[Foo alloc] init];
    self.foo = newFoo;
    [newFoo release];

    // bar is not automatically initialized, but can be set by something external
}

-(void)didTurnIntoFault {
    [foo release];
    foo = nil;
    [bar release];
    bar = nil;

    [super didTurnIntoFault];
}

@end

Теперь в моем приложении один экземпляр Root по запросу извлекается один раз при запуске приложения, и я сохраняю его до тех пор, пока приложение не закроется. (На самом деле это немного сложнее, потому что вы можете удалить корневой экземпляр и создать новый, но не более одного существует одновременно и сохраняется.) Поэтому я надеюсь, что didTurnIntoFault никогда не будет вызываться, пока мое приложение не закроется. Если это произойдет, то в какой-то момент я обращусь к root.foo или root.bar и получу ноль. Это было бы ошибкой для моего приложения. Экземпляр Root всегда должен иметь ненулевое значение для foo и bar; foo создается всякий раз, когда загружается экземпляр, и вызывающая сторона устанавливает панель сразу после извлечения корневого экземпляра.

Могу ли я рассчитывать на то, что didTurnIntoFault не вызывается, если мой код сохраняет NSManagedObject?

Если я не хочу вызывать didTurnInfoFault, почему он у меня? Ну, мне нужно как-нибудь убраться. Возможно, мне действительно следует поместить этот код в dealloc, если я не хочу, чтобы эти переменные экземпляра были освобождены до тех пор, пока программа не закроется. Но я думаю, что прочитал некоторую документацию, которая не рекомендуется использовать dealloc для подклассов NSManagedObject.

Ответы [ 2 ]

2 голосов
/ 21 сентября 2011

Если ваш объект существует в базовом файловом хранилище, он может быть в любой момент отключен из-за предупреждений о нехватке памяти и т. Д.

Но из вашего кода похоже, что все, что вам нужно, это простое лениво-инициализированное свойство, то есть переопределить метод получения 'foo' следующим образом:

- (Foo *)foo
{
    if (!foo) {
        foo = [[Foo alloc] init];
    }

    return foo; // or [[foo retain] autorelease] if you need that safety
}

Это гарантированно не вернет nil, и вы все равно можете освободить и обнулить переменную экземпляра, если хотите в didTurnIntoFault. В следующий раз, когда получатель будет вызван, новый ivar будет снова инициализирован.

1 голос
/ 21 сентября 2011

Моя интерпретация документации заключается в том, что ваш объект не будет превращен в ошибку, если вы не сделаете это самостоятельно (refreshObject:mergeChanges и несколько других методов в документации: http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData/Articles/cdPerformance.html#//apple_ref/doc/uid/TP40003468-SW4).. Это также делает эксплозиюЯ советую вам не отменять dealloc, поэтому я бы сказал, что вы поступаете правильно. Однако было бы очень интересно услышать другие мысли по этой теме.

...