Reputation: 3760
I have a crash with the following log on iOS 12.0.1:
ImageIO: CFDataGetBytes: data: 0x28539b2f0 size: 154262 offset: 8 count: 8 dst: 0x16dbf86f0
External data reference cant find underlying file.
Fatal Exception: NSInternalInconsistencyException
0 CoreFoundation 0x23c2d7ef8 __exceptionPreprocess
1 libobjc.A.dylib 0x23b4a5a40 objc_exception_throw
2 CoreData 0x23efd5fc8 -[_PFExternalReferenceData getBytes:range:]
3 ImageIO 0x23e6c7178 IIOImageRead::getCFDataBytesAtOffset(void*, unsigned long, unsigned long)
4 ImageIO 0x23e6c6c38 IIOImageRead::getBytesAtOffset(void*, unsigned long, unsigned long)
5 ImageIO 0x23e711aa4 IIO_Reader_PNG::getImageCount(IIOImageReadSession*, IIODictionary*, int*, unsigned int*)
6 ImageIO 0x23e54c5d8 IIO_Reader::callGetImageCount(CGImageReadSession*, IIODictionary*, int*)
7 ImageIO 0x23e532194 IIOImageSource::updatedCount()
8 ImageIO 0x23e5367b4 CGImageSourceGetCount
9 UIKitCore 0x26960c1a4 _UIImageRefFromData
10 UIKitCore 0x268d4e15c -[UIImage(UIImagePrivate) _initWithData:preserveScale:cache:]
11 UIKitCore 0x268d48b7c +[UIImage imageWithData:]
12 MyApp 0x102239570 __48-[InfoPreviewController bindToPatient:]_block_invoke_2 (InfoPreviewController.m:83)
13 ReactiveObjC 0x1031f8004 -[RACSubscriber sendNext:] (RACSubscriber.m:72)
It seems that core data has the image, but when it tries to retrieve it, it fails.
How can I verify the data integrity in this case? I would like to handle this failure in a user friendly way instead of crashing the app.
Upvotes: 3
Views: 1090
Reputation: 9141
The crash can be caused by not having file access to the external storage folder.
So before accessing an object value with attribute.description?.allowsExternalBinaryDataStorage == true
, make sure you have access or get access to the folder where the Core Data SQLite database files are stored.
Upvotes: 0
Reputation: 643
This is caused by a known bug in Core Data external storage in iOS 12.0.x as discussed here: https://stackoverflow.com/a/52628198/2347353. There is no workaround, but the bug appears to be fixed in iOS 12.1.
To answer your question though, with a bit of hackery-pokery, you can get the filename where the data is supposed to be stored and check to see if it exists or not. If the file is missing, then you know that the corruption has happened so you can avoid reading the attribute, and therefore prevent the app from crashing.
None of this is documented, but the files seem to be stored in the _EXTERNAL_DATA
hidden directory in your app’s Documents folder with a filename that you can work out from a value that is saved to the data store.
This answer shows how to do this in Objective-C and is where I got a lot of the details from: https://stackoverflow.com/a/13497992/2347353. But for anyone trying this at home, please do heed the warnings that this is all based on Apple’s internal implementation details of Core Data and could stop working at any point in the future.
Upvotes: 2