I store colours in my binary Core Data store using a transformable attribute, specifying the class of the attribute as UIColor like so:
#import "CoreDataEntity+CoreDataClass.h"
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface CoreDataEntity (CoreDataProperties)
+ (NSFetchRequest<CoreDataEntity *> *)fetchRequest;
@property (nullable, nonatomic, retain) UIColor *transformable;
@property (nullable, nonatomic, copy) NSString *string;
@end
NS_ASSUME_NONNULL_END
In the iOS 11 Beta this has stopped working with an error like this :
NSUnderlyingException=value for key 'NS.objects' was of unexpected class 'UIColor'. Allowed classes are '{(\n NSDecimalNumber,\n NSData,\n NSUUID,\n NSNumber,\n NSDate,\n NSArray,\n NSOrderedSet,\n NSDictionaryMapNode,\n NSString,\n NSSet,\n NSDictionary,\n NSURL,\n NSNull\n)}'.}";
NSUnderlyingException = "Can't read binary data from file";
}
I managed to replicate the specific problem in an XCode project on GitHub (Must be run with the XCode Beta twice to get the error).
In the demo project the store type is controlled by NSPersistentStoreDescription and setting it to NSBinaryStoreType, which I do in the AppDelegate in the exanple project, and I add objects in application didFinishLaunchingWithOptions, otherwise it's the standard template from an iOS11 app with core data. Plus a small datamodel and classes.
If you run the project twice, the first time it creates the datastore and everything is fine. The second time, the datastore tries to open and crashes the app. This problem only seems to be related to binary datastores from what I can tell, if I use an SQL backed datastore it works. However, my app is in the wild and uses binary.
I've reported it to Apple as a bug and sought help on the developer forums, but Apple has not acknowledged the bug and no help was coming.
I'm getting a bit worried as the iOS11 release date draws nearer and I have no solution, my app just won't work in iOS11.
I've tried changing the property to NSData and seeing if it was possible to just unarchive the data, but it seems it's still stored internally as a UIColor somehow and the database just won't open.
Can anyone see a workaround? I have the app in the wild, and possibly pushing out an update to convert the datastores before iOS11 could work for some, but that isn't going to guarantee all users get the fix and they could lose their data.
EDIT 1: Radar number : 33895450
EDIT 2: It just occured to me that this applies to any transformable attribute in core data, the values supported in the error message are just the default property types.
EDIT 3: Just out of curiosity I filled out all the fields for the transformable attribute (it was never required before). I added "NSKeyedUnarchiveFromData" to value transformer name of the core data entity, it should be the default, but you never know. No effect. It must be using the value transformer anyway to know that it's a UIColor. I filled in the custom class field to be UIColor, no effect.
Edit 5 : I noticed earlier that UIColor now supports NSSecureCoding, should security somehow be the issue somehow overlooked in the other store typed.
Edit : Now that iOS is released, i’ve used one of my TSIs to further escalate this. Do i get them back if i have to use one to get them to fix their software?
Edit : Apple got back to me on my TSI, they said it’s under investigation, there is no workaround, and to wait on the bug. They refunded my TSI because they couldn’t help.
Edit 8: Same problem on macOS High Sierra, with NSColor instead of UIColor.
Apple still have not given me any feedback on my actual bug report.
Well Apple got back to me, there are new persistentStore options!
The text I got from apple:
It's not immediately clear, but basically you have to supply an NSSet of classes you use as transformable attributes that comply with NSSecureCoding as an option when opening your persistent store.
An example for mine using the UIColor :
EDIT: Adding a solution for the newer way to open core data persistent stores using NSPersistentStoreDescription. This code is based on the current core data template.
I also updated my gitHub project with the fix in a branch