Мое приложение использует основные данные для хранения данных, и я добавил код, который обрабатывает случаи, когда база данных / модель не совместима / повреждена / и т. Д.В этом случае я выведу сообщение об ошибке, предлагающее пользователю стереть все данные и перезапустить приложение, чтобы пользователь мог начать заново с нуля.
Проблема в том, что приложение вылетаетпосле того, как хранилище было удалено, и пользователь нажал домашнюю кнопку.Мой код очистки выглядит следующим образом:
// destroy context
if ([__managedObjectContext hasChanges])
[__managedObjectContext rollback];
[__managedObjectContext release];
__managedObjectContext = nil;
// remove store
if (__persistentStoreCoordinator.persistentStores.count)
[__persistentStoreCoordinator removePersistentStore:[__persistentStoreCoordinator persistentStoreForURL:localURL] error:nil];
NSLog(@"retain count: %p %d", __persistentStoreCoordinator, __persistentStoreCoordinator.retainCount);
[__persistentStoreCoordinator release];
__persistentStoreCoordinator = nil;
Интересно, что счетчик сохранения NSPersistentStoreCoordinator
равен 1, поэтому в вышеприведенном выпуске освобождается объект.
Когда пользователь теперь нажимает домашнюю кнопкуЯ получу это в консоли:
*** -[NSPersistentStoreCoordinator retain]: message sent to deallocated instance 0x8345530
Напечатанный адрес 0x8345530
в этом примере равен объекту NSPersistentStoreCoordinator
, выпущенному в приведенном выше коде.Обратная трассировка выглядит следующим образом:
(gdb) bt
#0 0x0178be1e in ___forwarding___ ()
#1 0x0178bce2 in __forwarding_prep_0___ ()
#2 0x0122c75e in -[_NSSQLCoreConnectionObsever _purgeCaches:] ()
#3 0x00345a39 in __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 ()
#4 0x017f0885 in ___CFXNotificationPost_block_invoke_0 ()
#5 0x017f07a8 in _CFXNotificationPost ()
#6 0x0028a1aa in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#7 0x005e6169 in -[UIApplication _handleApplicationSuspend:eventInfo:] ()
#8 0x005ee8bd in -[UIApplication handleEvent:withNewEvent:] ()
#9 0x005ef1f8 in -[UIApplication sendEvent:] ()
#10 0x005e2aa9 in _UIApplicationHandleEvent ()
#11 0x01e45fa9 in PurpleEventCallback ()
#12 0x017f91c5 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ ()
#13 0x0175e022 in __CFRunLoopDoSource1 ()
#14 0x0175c90a in __CFRunLoopRun ()
#15 0x0175bdb4 in CFRunLoopRunSpecific ()
#16 0x0175bccb in CFRunLoopRunInMode ()
#17 0x01e44879 in GSEventRunModal ()
#18 0x01e4493e in GSEventRun ()
#19 0x005e0a9b in UIApplicationMain ()
#20 0x000046fd in main (argc=1, argv=0xbffff63c) at main.m:24
После полного перезапуска приложение, конечно, снова будет работать нормально, с простым новым и пустым файлом хранилища.
Приведенный выше код взят из моегоподкласс делегата приложения, и свойства объявлены так:
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@synthesize managedObjectContext = __managedObjectContext;
@synthesize persistentStoreCoordinator = __persistentStoreCoordinator;
Чего я просто не понимаю, так это как любой объект может по-прежнему использовать экземпляр координатора хранилища OLD, когда retaincount явно достигнет нуля?Я никогда не использую / не получаю доступ к этому объекту вне класса делегата приложения.
[править] Просто запускал инструменты (режим зомби), который дает похожие результаты:
http://i41.tinypic.com/317ci91.jpg
Как уже видно из следа, какой-то метод очистки кеша вызывает сбой.Что это такое, и как я могу сделать так, чтобы он использовал экземпляр НОВОГО координатора магазина, а не экземпляр зомби?