2015-04-08 3 views
0

Я использую основные данные в своем проекте iOS.Не удается создать промежуточный файл externalDataReference

Я использую несколько контекстов следующим образом. У меня есть persisent store context, который работает в частной очереди и сохраняет изменения в постоянном хранилище.

У меня есть main queue context, то есть ребенок persistent store context. Все из FRC s в моем приложении используют этот контекст.

И, наконец, если мне нужно внести некоторые изменения, которые я хочу сохранить в пакете, я создаю и использую новые NSManagedObjectContext s, которые являются дочерними элементами контекста главной очереди.

Так что у меня цепь:

DB < persistent store context < main queue context < any other child contexts 

У меня есть одиночки, который сохраняет как persistent store context и main queue context. Это одноточечно также слушает NSManagedObjectContextObjectsDidChangeNotification уведомления о persistent store context и реагирует на уведомление, как это:

-(void) persistentStoreContextDidChangeNotification:(NSNotification*)notification 
{ 
    if (notification.object == self.persistentStoreContext) { 
     [self.persistentStoreContext performBlockAndWait:^{ 
      //on every change on persistentStoreContext, save those changes using background thread to real persistent store 
      NSError *error = nil; 
      [self.persistentStoreContext save:&error]; 
     }]; 
    } 
} 

Так что, когда я называю [mainQueueContext save], этого достаточно для всех изменений в mainQueueContext будет упорствовать в файловой системе.

Использования Crashlytics, я получаю много сообщений о сбоях, как это:

Fatal Exception: NSInternalInconsistencyException 
Can't create externalDataReference interim file : 28 

Thread : Fatal Exception: NSInternalInconsistencyException 
0 CoreFoundation     0x0000000183f51e48 __exceptionPreprocess + 132 
1 libobjc.A.dylib    0x000000019464c0e4 objc_exception_throw + 60 
2 CoreData      0x0000000183c6e5b4 +[_PFRoutines writePFExternalReferenceDataToInterimFile:] + 960 
3 CoreData      0x0000000183ceaa4c -[NSSQLCore writeExternalDataReferences] + 224 
4 CoreData      0x0000000183c429fc -[NSSQLCore saveChanges:] + 596 
5 CoreData      0x0000000183c0b078 -[NSSQLCore executeRequest:withContext:error:] + 720 
6 CoreData      0x0000000183cd2254 __65-[NSPersistentStoreCoordinator executeRequest:withContext:error:]_block_invoke + 4052 
7 CoreData      0x0000000183cd9654 gutsOfBlockToNSPersistentStoreCoordinatorPerform + 180 
8 libdispatch.dylib    0x0000000194c9136c _dispatch_client_callout + 16 
9 libdispatch.dylib    0x0000000194c9a6e8 _dispatch_barrier_sync_f_invoke + 76 
10 CoreData      0x0000000183ccccb4 _perform + 180 
11 CoreData      0x0000000183c0ac34 -[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 300 
12 CoreData      0x0000000183c31400 -[NSManagedObjectContext save:] + 1284 
13 MyApp       0x00000001000d17e0 __58-[XEECDStack persistentStoreContextDidChangeNotification:]_block_invoke (XEECDStack.m:426) 
14 CoreData      0x0000000183ca5270 developerSubmittedBlockToNSManagedObjectContextPerform + 200 
15 CoreData      0x0000000183ca5474 -[NSManagedObjectContext performBlockAndWait:] + 232 
16 MyApp       0x00000001000d1774 -[XEECDStack persistentStoreContextDidChangeNotification:] (XEECDStack.m:423) 
17 CoreFoundation     0x0000000183ef81e0 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 20 
18 CoreFoundation     0x0000000183e37370 _CFXNotificationPost + 2060 
19 Foundation      0x0000000184d32cc0 -[NSNotificationCenter postNotificationName:object:userInfo:] + 72 
20 CoreData      0x0000000183c33d14 -[NSManagedObjectContext(_NSInternalChangeProcessing) _createAndPostChangeNotification:withDeletions:withUpdates:withRefreshes:] + 364 
21 CoreData      0x0000000183c321bc -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] + 2552 
22 CoreData      0x0000000183cadba4 -[NSManagedObjectContext(_NestedContextSupport) _parentProcessSaveRequest:inContext:error:] + 1568 
23 CoreData      0x0000000183cae684 __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke + 600 
24 CoreData      0x0000000183cb0398 internalBlockToNSManagedObjectContextPerform + 108 
25 libdispatch.dylib    0x0000000194c9136c _dispatch_client_callout + 16 
26 libdispatch.dylib    0x0000000194c9a6e8 _dispatch_barrier_sync_f_invoke + 76 
27 CoreData      0x0000000183ca06cc _perform + 208 
28 CoreData      0x0000000183cae354 -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:] + 176 
29 CoreData      0x0000000183c31400 -[NSManagedObjectContext save:] + 1284 
30 MyApp       0x000000010012ea14 __78-[MyAppManager downloadMediaIfNeededForMyAppWithManagedObjectID:onCompletion:]_block_invoke (MyAppManager.m:415) 
31 MyApp       0x00000001001ce06c __38-[FLNMyAppMediaDownloadOperation main]_block_invoke60 (FLNMyAppMediaDownloadOperation.m:84) 
32 Foundation      0x0000000184e07508 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 16 
33 Foundation      0x0000000184d58c94 -[NSBlockOperation main] + 96 
34 Foundation      0x0000000184d4861c -[__NSOperationInternal _start:] + 636 
35 Foundation      0x0000000184e0a26c __NSOQSchedule_f + 228 
36 libdispatch.dylib    0x0000000194c9136c _dispatch_client_callout + 16 
37 libdispatch.dylib    0x0000000194c95980 _dispatch_main_queue_callback_4CF + 932 
38 CoreFoundation     0x0000000183f096a0 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12 
39 CoreFoundation     0x0000000183f07748 __CFRunLoopRun + 1492 
40 CoreFoundation     0x0000000183e351f4 CFRunLoopRunSpecific + 396 
41 GraphicsServices    0x000000018cfcb5a4 GSEventRunModal + 168 
42 UIKit       0x0000000188766784 UIApplicationMain + 1488 
43 MyApp       0x0000000100119cc8 main (main.m:17) 
44 libdyld.dylib     0x0000000194cbaa08 start + 4 

Таким образом, в данной конкретной аварии, линии

30 MyApp       0x000000010012ea14 __78-[MyAppManager downloadMediaIfNeededForMyAppWithManagedObjectID:onCompletion:]_block_invoke (MyAppManager.m:415) 

зовут [mainQueueContext save]. Такая же авария происходит в ситуациях, когда [mainQueueContext save] вызывается из разных частей приложения.

Я пытаюсь выяснить, каковы возможные причины, по которым я вижу это исключение. И я ничего не могу найти на Google при поиске "Can't create externalDataReference interim file"

EDIT

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

дифферент 'версии' этой аварии являются:

Fatal Exception: NSInternalInconsistencyException 
External data reference can't find underlying file. 

,

Fatal Exception: NSInternalInconsistencyException 
Missing bytes from file at path /private/var/mobile/Containers/Data/Application/E9D51467-7941-41B8-88EE-31A70A82BC40/tmp/.LINKS/BD171390-D95C-459E-96D6-462318016138/EDB75A4F-C8FD-4BC4-ABD1-BA408F3A7DC9_0x18038c80, expected 276428, got 4294967295 

,

Fatal Exception: NSInvalidArgumentException 
Unable to open file with path: /var/mobile/Containers/Data/Application/19E53BC4-7891-4B0C-9454-27C1A0DAB2A0/Documents/persistent-store/.Model_SUPPORT/_EXTERNAL_DATA/CA6BCE7D-0C74-41CF-8784-8EB1F66DFF4C (13) 

,

Fatal Exception: NSInternalInconsistencyException 
This NSPersistentStoreCoordinator has no persistent stores. It cannot perform a save operation. 

Кроме того, я обнаружил шаблон, разделяемый почти всеми авариями этого типа. Доступное дисковое пространство на устройстве крайне низкое. На устройствах iPhone 4 и iPhone 5 доступное дисковое пространство составляет 0%. А на iPhone 6 это всегда 8%.

Я подозреваю, что iPhone 6 резервирует 8% дискового пространства «для особых случаев».

+0

@anacajic, вы решить эту проблему, или же вы пришли остроумие какие-либо выводы? У меня такая же проблема. Altho из crashlogs я вижу, что устройства работают на RAM, а не на диске. Я рассматриваю проблемы с памятью в своем приложении. Интересно, что это происходит только на iPad Air 2. – lukewar

+0

Было мало что я мог сделать, если пользователь заполнил диск до последнего байта. Приложение загружает фотографии и сохраняет их в Core Data. Я убедился, что, если диск находится на низком уровне, я регулярно чищу основные данные. Я информирую пользователей о том, что им необходимо очистить дисковое пространство, или они столкнутся с проблемами. Я не уверен, произойдет ли это из-за давления памяти. Я так не думаю. Давление в памяти создает различный журнал аварий. – ancajic

ответ

1

Я использую подобный процесс в моем приложении, с двумя контекстов установлены во время строительства моего основного стека данных и использования:

  • NSPrivateQueueConcurrencyType,
  • NSMainQueueConcurrencyType.

Чтобы угадать, блоки могут противоречить действию уведомления, однако это предположение.

Для моего приложения я изменил решение, представленное Маркусом Заррой в его книге «Прагматическая книжная полка» - «Основные данные, второе издание, хранилище данных и управление для iOS, OS X и iCloud» (январь 2013 г.).

Для получения более актуального и всеобъемлющего решения, которое я еще не реализовал, прочитайте эту статью My Core Data Stack от Zarra.

Мое модифицированное решение включает в себя создание пользовательского метода сохранения, созданного рядом (в том же классе), что и мой основной стек данных, как показано ниже, вместо использования NSManagedObjectContextObjectsDidChangeNotification. Обратите внимание, что метод сохранения вызывается в соответствующих точках кода.

Возможно, это подходящая альтернатива?

Свойства ...

@property (nonatomic, strong) NSManagedObjectContext *mocPrivate; 
@property (nonatomic, strong) NSManagedObjectContext *mocMain; 

Пользовательские метод сохранения ...

- (void)saveContextAndWait:(BOOL)wait { 
    if ([self.mocMain hasChanges]) { 
     [self.mocMain performBlockAndWait:^{ 
      NSError __autoreleasing *error; 
      BOOL success; 
      if (!(success = [self.mocMain save:&error])) 
       NSLog(@"%@ - %@ - CORE DATA - E~R~R~O~R saving managedObjectContext MAIN: %@, %@", NSStringFromClass(self.class), NSStringFromSelector(_cmd), error.localizedDescription, error.localizedFailureReason); 
      NSLog(@"%@ - %@ - CORE DATA - Success saving managedObjectContext MAIN?: %@", NSStringFromClass(self.class), NSStringFromSelector(_cmd), success ? @"YES_" : @"NO_"); 
     }]; 
    } 

    void (^savePrivate) (void) = ^{ 
     NSError __autoreleasing *error; 
     BOOL success; 
     if (!(success = [self.mocPrivate save:&error])) 
      NSLog(@"%@ - %@ - CORE DATA - E~R~R~O~R saving managedObjectContext PRIVATE: %@, %@", NSStringFromClass(self.class), NSStringFromSelector(_cmd), error.localizedDescription, error.localizedFailureReason); 
     NSLog(@"%@ - %@ - CORE DATA - Success saving managedObjectContext PRIVATE?: %@", NSStringFromClass(self.class), NSStringFromSelector(_cmd), success ? @"YES_" : @"NO_"); 
    }; 

    if ([self.mocPrivate hasChanges]) { 
     if (wait) { 
      [self.mocPrivate performBlockAndWait:savePrivate]; 
     } else { 
      [self.mocPrivate performBlock:savePrivate]; 
     } 
    } 
} 
0

мне удалось воспроизвести этот вопрос, заполнив все пространство на устройстве, а затем с помощью приложения, хранение носителей в Core Data.

По прошествии некоторого времени использования приложения всплывающее окно предупреждения показывает, что на устройстве недостаточно места на диске. Я отклоняю предупреждение и продолжаю использовать приложение. Через некоторое дополнительное время, то приложение падает с сообщением:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Can't create externalDataReference interim file : 28' 
Смежные вопросы