Is there a way with Core Data to store a non-standard property value to a string entity attribute? I attempted to do this by creating an NSValueTransformer subclass that transforms NSURL to NSString, simply returning the result of NSURL:absoluteString. My transformer also returns [NSString class] from +transformedValueClass. I then created a transformable type attribute, aUrl, on my entity in the model editor, set the transformer name to my transfomer, and the custom class to NSURL. My NSManagedObject subclass has a correlating @property (nonatomic) NSURL *aUrl. When I assign an NSURL object to that property and attempt to save the NSManagedObjectContext, the app crashes with the following exception.
2017-06-30 06:28:15.257 PhotoLocations[73116:3990254] -[__NSCFString bytes]: unrecognized selector sent to instance 0x608000075bc0
2017-06-30 06:28:15.292 PhotoLocations[73116:3990254] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString bytes]: unrecognized selector sent to instance 0x608000075bc0'
*** First throw call stack:
(
0 CoreFoundation 0x000000010e080b0b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000010dae5141 objc_exception_throw + 48
2 CoreFoundation 0x000000010e0f0134 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x000000010e007840 ___forwarding___ + 1024
4 CoreFoundation 0x000000010e0073b8 _CF_forwarding_prep_0 + 120
5 CoreData 0x000000010d6e09e7 -[NSSQLiteConnection execute] + 1063
6 CoreData 0x000000010d723e12 -[NSSQLiteConnection insertRow:] + 450
7 CoreData 0x000000010d8b7ad0 _writeChangesForSaveRequest + 1056
8 CoreData 0x000000010d8b9546 _executeSaveChangesRequest + 390
9 CoreData 0x000000010d750fb6 -[NSSQLSaveChangesRequestContext executeRequestUsingConnection:] + 38
10 CoreData 0x000000010d863908 __52-[NSSQLDefaultConnectionManager handleStoreRequest:]_block_invoke + 216
11 libdispatch.dylib 0x000000010f8dd05c _dispatch_client_callout + 8
12 libdispatch.dylib 0x000000010f8bade6 _dispatch_barrier_sync_f_invoke + 346
13 CoreData 0x000000010d8637db -[NSSQLDefaultConnectionManager handleStoreRequest:] + 235
14 CoreData 0x000000010d86aba6 -[NSSQLCoreDispatchManager routeStoreRequest:] + 342
15 CoreData 0x000000010d7eed55 -[NSSQLCore dispatchRequest:withRetries:] + 229
16 CoreData 0x000000010d7eb64d -[NSSQLCore processSaveChanges:forContext:] + 189
17 CoreData 0x000000010d6e7541 -[NSSQLCore executeRequest:withContext:error:] + 881
18 CoreData 0x000000010d7d6a8b __65-[NSPersistentStoreCoordinator executeRequest:withContext:error:]_block_invoke + 4363
19 CoreData 0x000000010d7ceb6d -[NSPersistentStoreCoordinator _routeHeavyweightBlock:] + 381
20 CoreData 0x000000010d6e6f98 -[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 632
21 CoreData 0x000000010d70f488 -[NSManagedObjectContext save:] + 3368
22 PhotoLocations 0x000000010b0e676c -[APLRootViewController addEvent:] + 1084
23 UIKit 0x000000010b24fd82 -[UIApplication sendAction:to:from:forEvent:] + 83
24 UIKit 0x000000010b68a917 -[UIBarButtonItem(UIInternal) _sendAction:withEvent:] + 149
25 UIKit 0x000000010b24fd82 -[UIApplication sendAction:to:from:forEvent:] + 83
26 UIKit 0x000000010b3d45ac -[UIControl sendAction:to:forEvent:] + 67
27 UIKit 0x000000010b3d48c7 -[UIControl _sendActionsForEvents:withEvent:] + 450
28 UIKit 0x000000010b3d4a3b -[UIControl _sendActionsForEvents:withEvent:] + 822
29 UIKit 0x000000010b3d3802 -[UIControl touchesEnded:withEvent:] + 618
30 UIKit 0x000000010b2bd7ea -[UIWindow _sendTouchesForEvent:] + 2707
31 UIKit 0x000000010b2bef00 -[UIWindow sendEvent:] + 4114
32 UIKit 0x000000010b26ba84 -[UIApplication sendEvent:] + 352
33 UIKit 0x000000010ba4f5d4 __dispatchPreprocessedEventFromEventQueue + 2926
34 UIKit 0x000000010ba47532 __handleEventQueue + 1122
35 CoreFoundation 0x000000010e026c01 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
36 CoreFoundation 0x000000010e00c0cf __CFRunLoopDoSources0 + 527
37 CoreFoundation 0x000000010e00b5ff __CFRunLoopRun + 911
38 CoreFoundation 0x000000010e00b016 CFRunLoopRunSpecific + 406
39 GraphicsServices 0x000000010f011a24 GSEventRunModal + 62
40 UIKit 0x000000010b24e134 UIApplicationMain + 159
41 PhotoLocations 0x000000010b0e36df main + 111
42 libdyld.dylib 0x000000010f92965d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
I verified that Core Data is calling my transformer before the exception occurs. So Core Data appears to expect an NSData value from the NSValueTransformer. regardless of the class of the value my transformer produces. Indeed, I inspected the sqlite database Core Data produced, and the corresponding table column for aUrl is of type BLOB.
The goal was to easily transition an existing app to use Core Data without having to change all the code that uses NSURL values to use NSString, while having the ability filter based on the NSURL string values.
Is there any way to make Core Data store my NSURL properties as strings, or must I change to use NSString or some transient/derived property with custom accessors? The Apple docs are pretty vague on the latter, as far as I can tell.
Thank you.