无法创建 externalDataReference 临时文件

Posted

技术标签:

【中文标题】无法创建 externalDataReference 临时文件【英文标题】:Can't create externalDataReference interim file 【发布时间】:2015-04-08 12:14:46 【问题描述】:

我在我的 ios 项目中使用 Core Data。

我通过以下方式使用多个上下文。我有一个persisent store context,它在私有队列上运行并将更改存储到持久存储中。

我有一个main queue context,它是persistent store context 的孩子。我的应用程序中的所有FRCs 都使用此上下文。

最后,如果我必须进行一些想要批量保存的更改,我会创建并使用新的NSManagedObjectContexts,它们是主队列上下文的子级。

所以我有一个链条:

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

我有一个同时保留persistent store contextmain queue context 的单例。这个单例还会在persistent store context 上监听NSManagedObjectContextObjectsDidChangeNotification 通知,并对通知做出如下反应:

-(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] 的情况下也会发生同样的崩溃。

我正在尝试找出我看到此异常的可能原因。搜索 "Can't create externalDataReference interim file" 时,我在 Google 上找不到任何东西

编辑

我已经经历了特定的崩溃实例,并一一查看了它们。尽管每次崩溃的堆栈跟踪都非常相似,但事实证明,实例之间的异常略有不同。

这次崩溃的不同“版本”是:

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% 的磁盘空间。

【问题讨论】:

@anacajic,您解决了这个问题还是得出了任何结论?我有类似的问题。从崩溃日志中我可以看到设备在 RAM 内存而不是磁盘空间上运行不足。我正在考虑我的应用程序中的内存问题。有趣的是,它只发生在 iPad Air 2 上。 如果用户将磁盘填充到最后一个字节,我只能做很少的事情。该应用程序下载照片并将它们保存到 Core Data。我确保,如果磁盘空间不足,我会定期清理核心数据。我让用户意识到他们需要清除一些磁盘空间,否则他们会遇到问题。我不确定这是否会由于内存压力而发生。我不这么认为。内存压力产生不同的崩溃日志。 【参考方案1】:

我在我的应用程序中使用了类似的过程,在构建核心数据堆栈期间设置了两个上下文并使用:

NSPrivateQueueConcurrencyType, NSMainQueueConcurrencyType

猜测一下,这些块可能与通知的操作发生冲突,但这只是猜测。

对于我的应用,我修改了 Marcus Zarra 在他的 The Pragmatic Bookshelf 书中提出的解决方案——“Core Data, 2nd Edition, Data Storage and Management for iOS, OS X, and iCloud”(2013 年 1 月)。

有关我尚未实施的更新和全面的解决方案,请阅读 Zarra 的这篇文章 My Core Data Stack。

我修改后的解决方案包括编写一个自定义保存方法,该方法与我的核心数据堆栈(在同一个类中)一起构建,如下所示,而不是使用NSManagedObjectContextObjectsDidChangeNotification。请注意,在代码中的适当位置调用 save 方法。

也许这是一个合适的选择?

属性...

@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];
        
    

【讨论】:

【参考方案2】:

我设法通过填满设备上的整个磁盘空间,然后使用应用程序,将媒体存储在 Core Data 中来重现此问题。

使用该应用一段时间后,会弹出一个警告窗口,显示设备磁盘空间不足。我忽略了警告并继续使用该应用程序。 再过一段时间,应用程序崩溃并显示以下消息:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Can't create externalDataReference interim file : 28'

【讨论】:

现在是 2018 年,所以距离发布已经有一段时间了.. 但仍然.. 你有没有机会回忆/弄清楚你是如何获得 External data reference can't find underlying file. 我正在使用模拟器。遇到同样的问题。

以上是关于无法创建 externalDataReference 临时文件的主要内容,如果未能解决你的问题,请参考以下文章

UE4无法创建C++项目

Android 错误:“无法创建 epoll 实例”或“无法创建唤醒管道”

虚拟桌面无法创建的问题

无法创建临时文件夹错误5拒绝访问

警告1909,无法创建快捷方式。怎么办?

创建EXCEL对象失败,请确认已正确安装Excel程序?