RESTKit serializing nil to JSON - iphone

I'm new to RESTKit 0.20, but I was wondering, is it possible as of right now to serialize an object's nil instance variable to JSON?
To be precise, I want to serialize NSString that is nil

This feature is added in a recent (at time of writing) commit: bb34247aef19d40b725bdcc8e96466f80a033124. So it requires you to use at least v0.22.0
The linked commit includes a number of new tests which show the mapping in action.

Related

Deleting Core Data elements with unwrapped optionals

I have a Core Data Entity with a Date attribute (e.g. current_date. Technically, in the Class which Core Data generates for that Entity, this attribute is optional (#NSManaged public var current_date: Date?). However, in my app this Date is always provided, which is why in the View I am displaying this fetched Entity via a list, I am force unwrapping it with current_date!. This all works fine so far. However, I have added an onDelete to that list to be able to delete single elements and now I am getting a bug Fatal error: Unexpectedly found nil while unwrapping an Optional value. Seems to be some problem related to the deletion process - as said, that value in the data is actually never empty. Does anyone know what is the problem here?
Your code may not set current_date to nil. But if you
Delete a managed object object
Save changes
Try to use that same managed object reference
...then current_date is nil, because that's something Core Data does. This error message suggests that you are attempting to use the object after deleting it and saving changes. Ideally you should fix that, because you won't have valid data anyway. You should also avoid force-unwrapping anyway, because using it is a way of specifically requesting app crashes any time you use it.

SwiftUI NSData comparing non-optional value which is actually optional [duplicate]

I have a core data entity named Film which has properties title and date. I noticed that the generated NSManagedObject subclass contains optional NSManaged properties even though I marked the properties as non optional in the core data inspector.
Can I can manually change it as non-optional property or is it a better choice to leave it as optional? Why?
"Optional" means something different to Core Data than it does to Swift.
If a Core Data attribute is not optional, it must have a non-nil value when you save changes. At other times Core Data doesn't care if the attribute is nil.
If a Swift property is not optional, it must have a non-nil value at all times after initialization is complete.
Making a Core Data attribute non-optional does not imply that it's non-optional in the Swift sense of the term. That's why generated code makes these properties optional-- as far as Core Data is concerned, it's legal to have nil values except when saving changes.
Update: After writing this answer I wrote a deep dive blog post explaining things in more detail: https://www.atomicbird.com/blog/clash-of-the-optionals/
This is a known issue. Some people change it to non-optional with no adverse effects, I keep it the way it was generated and hope for early fix.
It always helps if you submit a bug to Apple to increase visibility and priority.
Create managedobject class and change the entity class type to manual and add these classes to your project scope.
Edit your managedObject to make them non-optional. This means you need to maintain this class yourself and do any changes both in the core data model and the class
If your data model is stable and won't be changed then you can use this.
The Optional checkbox in the data model inspector has nothing to do with Swift optionals. The checkbox determines whether or not the attribute is required to have a value.
If you deselect the Optional checkbox for an attribute, you must give that attribute a value or you will get an error when saving. By selecting the Optional checkbox you can save without giving the attribute a value. Suppose you have a description attribute that's a string. If you select the Optional checkbox you could leave the description blank and still save the entity.
Here's another example. Suppose you have text fields to let a person enter their home, work, and cell phone numbers. These phone numbers should be optional attributes. You wouldn't want to require someone to have a home phone number, a work phone number, and a cell phone number just to save the person's data.

What is a good pattern for interpreting Core Data validation messages and displaying them on the iPhone?

I've implemented a small proof-of-concept app using Core Data to accept some object attribute values from the user via text fields and it's all working great thanks to information found here and in the iPhone Core Data Recipes app. But I'm at the point where I need to display object validation errors to the user and I can't find a recommended way of handling this. The code in the Recipe app just logs the error and says to "Replace this implementation with code to handle the error appropriately." Great, thanks.
I'm sure there are a multitude of ways to interpret, parse and transmit the validation error information to the user but what I'd like to know is if there are some best practices or a pattern that someone has implemented that I could follow. Where should the validation code like [newObject valdiateForInsert&error]; be placed? In NSManagedObject subclasses? In the UIViewController that handles the screen the enables the object to be added? Maybe in an app-wide ValidationController?
All the validation errors are returned in the NSError's userInfo, which is a NSDictionary of various NSValidation keys and values. Is there a good way of translating this error info into something that would be helpful to the user? For example, I have a rule in my Core Data model that a certain attribute can only be 3 characters long. If in the process of saving or updating an object I get a validation error, I need to parse out the NSError userInfo and find values for the NSValidationErrorKey (the name of the attribute), the NSValidationErrorValue (the value on the object that caused the error) and the NSValidationErrorPredicate (the rule that was violated, which in this case returns length <= 3.
Is there a good, generally accepted way of gathering and munging this data into something that can be passed back to the user? I'm currently pulling the NSError info into strings and then falling through a series of conditional statements for each attribute that I'm validating, and it's so ugly that I kinda want to puke when I look at it. There has to be a better, cleaner way to consume Core Data validation errors and pass a readable version to the user.
Validations are not there for the user. They are there so the code can maintain the integrity of the object graph. Validation methods are not called by the managed object context until the time at which context is saved. That time might be very distant from the time of input.
However, you can call an objects validation methods directly before you set an attribute. The validation methods have the form:
- (BOOL)validateTimeStamp:(id *)valueRef error:(NSError **)outError;
Suppose you have an attribute name for a managed object subclass PeopleMO. The validation method to check for an empty string might look like:
- (BOOL)validateName:(id *)valueRef error:(NSError **)outError{
BOOL isValid=NO;
NSString *toTest=(NSString *) valueRef;
if (![toTest isEqualToString:#""]) {
isValid=YES;
}
return isValid;
}
You could call it anywhere like:
NSString *newName=// some UI element text
PersonMO *newPerson=//.. insert new PersonMO object
if ([newPerson validateName:newName error:nil]) {
newPerson.name=newName;
}else{
//... inform user name is invalid
// ... possibly delete newPerson object from context
}
This is most useful where you have situations in which the validity of the value of one attribute depends on one or more other attributes of the same object.

Couldn't I just pass an copied string to an Core Data property?

The docs say:
The default implementation does not
copy attribute values. If the
attribute value may be mutable and
implements the NSCopying protocol (as
is the case with NSString, for
example), you can copy the value in a
custom accessor to help preserve
encapsulation (for example, in the
case where an instance of
NSMutableString is passed as a value).
So instead of getting into trouble and inconvenience with overwriting accessors in my NSManagedObject subclass, couldn't I simply do something like this?
myManagedObject.firstName = [[firstNameMutableStr copy] autorelease];
This would have the exact same effect, or not? The dynamic implementation would retain that anyways ... so.... why not the easy way?
It's an open question whether having to remember to copy the mutable string every where in code you set the attribute is "the easy way."
With a custom accessor, you just write the copy once then forget about. It copies automatically from that point on.
Just imagine that in thousands of lines of code you forgot to copy just once and developed a subtle bug because that one attribute of the managed object sporadically changed because some other totally unrelated code subsequently changed the mutable string you held only by reference.
I could tell you some stories of weekends lost to debugging because someone took "the easy way."

setPropertiesToFetch method appears to always make request return faulted objects

Whenever I use setPropertiesToFetch on an NSFetchRequest, the objects that are returned appear to all be faulted. They return YES to isFaulted and when displaying them in the console they appear like this:
< MyEntity: 0x5884850> (entity: MyEntity; id: 0x5886180 <x-coredata://4D96A1CB-187C-4D92-A50C-D639F7E69114/MyEntity/p197> ; data: <fault>),
Whereas if I don't set properties to fetch, every object's properties are visible in the console. Any idea why this is happening?
I've got an answer from the Apple Developer Forums:
https://devforums.apple.com/message/152330#152330
"The object being a fault means it might require a trip to the database, or it may mean that the object is pending lazy initialization and all the necessary data is cached. Tracking your app with the Core Data template in Instruments is the best way to empirically tell the difference.
For setPropertiesToFetch, you are intentionally not fetching all the properties, so you end up with a partial fault. Accessing some properties (the ones you told it to fetch) will work, and accessing others will require a round trip to the database. -isFault is a boolean, so most of the framework treats partial faults like they are just faults."
By default, Core Data will fetch objects as faults the first time they're loaded into the managed object context. It won't populate the attributes until you ask for them. If you need a fetch request to return non-faulted objects, you can use setReturnsObjectsAsFaults:YES
The documentation says that the value from -setPropertiesToFetch: is only used when resultType is set to NSDictionaryResultType.