Objective-C

 
11
Jan
2012
 

Handling incoming JSON redux

by Tom Harrington

A few months ago I wrote here about a generic approach to safely take incoming JSON and save values to Core Data object. The goals of that code were twofold:

  1. Provide a safe, generic alternative to Cocoa’s -setValuesForKeysWithDictionary: for use with NSManagedObject and its subclasses
  2. Handle cases where JSON data didn’t match up with what the managed objects expected. Getting a string where you expect a numeric value, or vice versa, for example, or getting a string representation of a date when you want a real NSDate object.

The first item was the most important. It’s tempting to use -setValuesForKeysWithDictionary: to transfer JSON to a model object in one step. The method runs through the dictionary and calls -setValue:forKey: on the target object for every entry. It has a fatal flaw though, in that it doesn’t check to see if the target object actually has a key before trying to set it. Using this method when you don’t have absolute control over the dictionary contents is an invitation to unknown key exceptions and nasty app crashes.

Fixing this for managed objects was relatively easy because Core Data provides convenient Objective-C introspection methods. The general approach was:

  • Get a list of the target object’s attributes
  • For each attribute, see if the incoming dictionary has an entry. If so,
    • Compare the incoming type to the expected type, and convert if necessary.
    • Call -setValue:forKey: with that key and its value.

And then just last week I had the thought, wouldn’t it be nice if this worked for any object, not just for managed objects?

Objective-C introspection

Since Objective-C is dynamic, pretty much everything you’d want to know about a class is available at run time. I’m not just talking about methods like -respondsToSelector: and -isKindOfClass:, though those are extremely useful. You can go much, much deeper than that, inspecting (and even changing) every aspect of a class’s implementation. Much of this happens via C function calls rather than Objective-C method calls. The Objective-C runtime is not actually written in Objective-C, and it’s the runtime that has the information.

To update the code for use with objects that don’t inherit from NSManagedObject the new code looks through the properties declared on a class and uses those to run through the incoming JSON. The general approach is the same but the implementation uses NSObject properties instead of NSEntityDescription attributes.

It’s also possible to look through the instance variables instead of the properties. Often this would amount to the same thing. Where they differ is when the backing ivar has a different name, i.e. when you’re using something like:

@synthesize foo = __myReallyBizarrePrivateName____;

In that case iterating over properties would find foo while iterating over instance variables would find __myReallyBizarrePrivateName____. Either is valid but I’m going with the properties because (at least for me) they’re more likely to match up with the JSON keys.

First pass: iterating over properties

A simple version that meets requirement #1 looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (void)setValuesForKeysWithJSONDictionary:(NSDictionary *)keyedValues dateFormatter:(NSDateFormatter *)dateFormatter
{
    unsigned int propertyCount;
    objc_property_t *properties = class_copyPropertyList([self class], &propertyCount);
 
    for (int i=0; i<propertyCount; i++) {
        objc_property_t property = properties[i];
        const char *propertyName = property_getName(property);
        NSString *keyName = [NSString stringWithUTF8String:propertyName];
 
        id value = [keyedValues objectForKey:keyName];
        if (value != nil) {
            [self setValue:value forKey:keyName];
        }
    }
    free(properties);
}

This starts with a call to class_copyPropertyList(), which gets a C-style array of property declarations for the requested class. The propertyCount argument indicates how many properties are in the array. The array contains zero or more objc_property_t entries, which is an opaque structure.

The code iterates through this array. For each one it uses property_getName to get the property name as a C-style string. Then it converts this to an NSString and uses that to look up entries in the incoming dictionary. And, voila, we’re using the class’s own properties to look up values in the dictionary instead of the other way around.

A final detail– unusual in Objective-C code– is the call to free(). Since class_copyPropertyList() has copy in its name, the calling code is responsible for disposing of the returned data. And since it’s a C call, this needs to be done C style. This call would need to be there even if the project were using ARC.

Back to Core Data, briefly

The great thing about this solution is that it’s not the non-managed-object alternative to the previous version, it’s a direct replacement. This approach works just as well on managed objects as on other objects– provided, that is, that you create custom subclasses of NSManagedObject for your entities that declare properties for managed object attributes. So long as the properties exist, the code works. If you’re using Xcode or mogenerator to generate your managed object subclasses, you’re covered. If you aren’t creating custom subclasses, first of all, why not? But in that case this approach won’t work since NSManagedObject doesn’t have the necessary property declarations.

Does it have to be like this?

Some of you may have noticed that it’s possible to do the same thing without any mucking about with the runtime by doing something like this:

1
2
3
4
5
6
7
8
    for (NSString *key in keyedValues) {
        @try {
            [self setValue:[keyedValues objectForKey:key] forKey:key];
        }
        @catch (NSException *exception) {
            // Do nothing
        }
    }

In this case the dictionary keys still drive the action, but exception handling means the code doesn’t crash on unknown keys. So why bother then? Because of requirement #2 above. Coercing JSON into appropriate data types is going to require introspection. With this simplified approach you don’t crash, but you also don’t get type conversions. If not crashing is all you’re interested in, this works just as well and is probably faster. It’s certainly simpler anyway. It’s not going to do what I need though.

JSON Fixes

To meet requirement #2 the code needs to go deeper. As with the Core Data implementation, it needs to look up the expected value for the property and compare that to the type of the incoming data. To do this I’ll expand the if block beginning on line 12 above to look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
if (value != nil) {
    char *typeEncoding = NULL;
    typeEncoding = property_copyAttributeValue(property, "T");
 
    if (typeEncoding == NULL) {
        continue;
    }
    switch (typeEncoding[0]) {
        case '@':
        {
            // Object
            Class class = nil;
            if (strlen(typeEncoding) >= 3) {
                char *className = strndup(typeEncoding+2, strlen(typeEncoding)-3);
                class = NSClassFromString([NSString stringWithUTF8String:className]);
            }
            // Check for type mismatch, attempt to compensate
            if ([class isSubclassOfClass:[NSString class]] && [value isKindOfClass:[NSNumber class]]) {
                value = [value stringValue];
            } else if ([class isSubclassOfClass:[NSNumber class]] && [value isKindOfClass:[NSString class]]) {
                // If the ivar is an NSNumber we really can't tell if it's intended as an integer, float, etc.
                NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
                [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
                value = [numberFormatter numberFromString:value];
                [numberFormatter release];
            } else if ([class isSubclassOfClass:[NSDate class]] && [value isKindOfClass:[NSString class]] && (dateFormatter != nil)) {
                value = [dateFormatter dateFromString:value];
            }
 
            break;
        }
 
        default:
        {
            break;
        }
    }
    [self setValue:value forKey:keyName];
    free(typeEncoding);
}

The runtime provides information about properties via the call to property_copyAttributeValue() on line 3. The first argument is the property of interest. The second one can have a bunch of different values depending on what you want to look up. A “T” requests a C-style string that describes the property type. For full details on what you can do with the second argument, see the (somewhat out of date as of this writing) “Declared Properties” section of Apple’s Objective-C Runtime Programming Guide.

If the property type is a pointer to a class, the return value will be something like T@"NSNumber", T@"NSString", T@"MyClass", etc. The next thing the code does then is to check for a leading @ and, if found, set about getting the Class that the type string names. This happens in lines 12-16. The code strips off the @ and the quotes, converts to NSString, and uses NSClassFromString to get the Class.

The rest of this code is remarkably similar to the Core Data version, looking for type mismatches and converting the incoming value where needed. The chief difference is that it uses -isSubclassOfClass: to check on the expected type of the property instead of looking at the Core Data-specific NSAttributeType.

Except for one important difference. For numeric properties, the Core Data attribute type would indicate whether a floating point or integer value was expected. With NSNumber we have no way of knowing. So the code uses NSNumberFormatter to parse incoming strings and leaves it at that. If this kind of mismatch occurs then there are bigger problems anyway. You could change the code to round a float to an int, but is that actually going to be a valid result? Maybe, maybe not.

The type comparisons in this code could go on forever but in this case the code is specifically looking for problems that sometimes crop up with JSON.

Since property_copyAttributeValue() has copy in its name, this block adds another call to free() to clean up after itself.

Handling primitives

But what if the expected value is not an object at all? What if it’s a primitive int? Fortunately property_copyAttributeValue() covers that case as well. In this case the type encoding string is shorter, with values like Ti for int, Tf for float, TQ for unsigned long long, etc (again, see Apple’s docs for a full list).

With this information, the switch statement above can be expanded with a few more cases.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
        case 'i': // int
        case 's': // short
        case 'l': // long
        case 'q': // long long
        case 'I': // unsigned int
        case 'S': // unsigned short
        case 'L': // unsigned long
        case 'Q': // unsigned long long
        case 'f': // float
        case 'd': // double
        case 'B': // BOOL
        {
            if ([value isKindOfClass:[NSString class]]) {
                NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
                [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
                value = [numberFormatter numberFromString:value];
                [numberFormatter release];
            }
            break;
        }
 
        case 'c': // char
        case 'C': // unsigned char
        {
            if ([value isKindOfClass:[NSString class]]) {
                char firstCharacter = [value characterAtIndex:0];
                value = [NSNumber numberWithChar:firstCharacter];
            }
            break;
        }

The first half of this, up to line 20, handles all the numeric types. As with the previous code block there’s no attempt to work out floating point/integer conflicts since it’s impossible to know how to handle this in the general case. It would be possible to break this up into more specific checks, say by using -[NSString intValue] when an integer result is expected and hope for valid data. But the code above handles the case where you actually have an integer value, and if you don’t have one then again, you have bigger problems.

The rest of this block handles a primitive char property by taking the first character in the incoming string. Longer strings can’t be stored in a char anyway, so this is the best approach.

In both cases the conversion results in an NSNumber instead of a primitive type. That’s OK though– -setValue:forKey: has our back here and will unbox the object for us.

Conclusion

Using this approach makes it a lot easier to deal with web services. You can’t always rely on the results matching what you expect (or what’s documented). Inspecting classes at run time takes a more defensive approach to dealing with data you can’t control.

A category on NSObject that implements this code can be found at github.

 
2
Jun
2011
 

Saving JSON to Core Data

by Tom Harrington

Hi, I’m new here. You may know me as @atomicbird on Twitter. Just a few days ago my book Core Data for iOS: Developing Data-Driven Applications for the iPad, iPhone, and iPod touch (co-written with the excellent Tim Isted) was published, and Matt invited me to contribute some Core Data tips to CIMGF. I’m going to start off discussing taking JSON data from a web service and converting it to Core Data storage. Along the way I’ll cover how to inspect managed objects to find out what attributes they have and what the attribute types are.

Publishing lead times being what they are, this post covers information not included in the book. (more…)

 
4
May
2011
 

Core Data and Threads, Without the Headache

by Saul Mora

I know I mentioned we would talk about customizing the fetch requests, however, I have been working on some code related to the Active Record Fetching project, which I am renaming to MagicalRecord, that is also just as useful as fetching–threading.

Whenever most cocoa developers mention threading and Core Data in the same sentence, the reaction I see most often is that of mysticism and disbelief. For one, multithreaded programming in general is hard–hard to design correctly, hard to write correctly, and debugging threads is just asking for trouble. Introducing Core Data into that mix can seem like the straw that broke the camel’s back. However, by following a few simple rules and guidelines, and codifying them into a super simple pattern, one that may be familiar to you, we can achieve safer Core Data threading without the common headaches.

(more…)

 
13
Mar
2011
 

Super Happy Easy Fetching in Core Data

by Saul Mora

First up, I want to thank Matt Long and Marcus Zarra for allowing me to guest post on CIMGF. This post is the first in a short series of topics describing how to I’ve made using Core Data a little simpler without giving up the power features you still need. The full project from which this series is derived is available on github.

Core Data, for both iPhone and Mac, is a very powerful framework for persisting your objects out of memory, and into a more permanent storage medium. With the enormous power of Core Data, it can be easy to slip into the trap of thinking that Core Data is very complex.

(more…)

 
1
Mar
2011
 

Subduing CATiledLayer

by Matt Long

Many technologies we use as Cocoa/Cocoa Touch developers stand untouched by the faint of heart because often we simply don’t understand them and employing them can seem a daunting task. One of those technologies is found in Core Animation and is referred to as the CATiledLayer. It seems like a magical sort of technology because so much of its implementation is a bit of a black box and this fact contributes to it being misunderstood. CATiledLayer simply provides a way to draw very large images without incurring a severe memory hit. This is important no matter where you’re deploying, but it especially matters on iOS devices as memory is precious and when the OS tells you to free up memory, you better be able to do so or your app will be brought down. This blog post is intended to demonstrate that CATiledLayer works as advertised and implementing it is not as hard as it may have once seemed. (more…)

 
7
Jan
2011
 

Passing around a NSManagedObjectContext on iOS

by Marcus Zarra

This article is reprinted from the MDN

The documentation on Core Data for the iPhone has lead to some confusion about how best to use Core Data on a Cocoa Touch device. One particular section seems to be the most confusing, specifically:

A view controller typically shouldn’t retrieve the context from a global object such as the application delegate. This tends to make the application architecture rigid. Neither should a view controller typically create a context for its own use. This may mean that operations performed using the controller’s context aren’t registered with other contexts, so different view controllers will have different perspectives on the data.

When you create a view controller, you pass it a context. You pass an existing context, or (in a situation where you want the new controller to manage a discrete set of edits) a new context that you create for it. It’s typically the responsibility of the application delegate to create a context to pass to the first view controller that’s displayed.

The idea behind this section is the issue of rigidity. Ideally, each view controller should be an island on its own. It should not rely on its parent, nor should it rely on the Application Delegate. Once a view controller is pushed onto the screen it should ideally be its own master.

Why Rigidity is bad

It is fairly common when designing a Cocoa Touch application to “hard code” everything. Take the following navigation controller design:

Navigation Controller Design

When this design, it is common to code each view controller and make it “aware” of its parent. In that design, it would be common to see view controller B call methods or call back (to its delegate) view controller A. While there is nothing technically wrong with this design, it is very rigid. It is nearly impossible to either move view controller B to another location in the stack or to reuse view controller B somewhere else. This is the trap that the documentation is trying to help new developers avoid.

Solution One

Again using a standard/normal navigation controller design, it is expected that the detail flows from left to right. The left most (or root) view controller contains the most vague information and the right most (or deepest) view controller contains the greatest detail.

UIFetchedResultsController

In this case then the best solution is to use a UIFetchedResultsController. This controller can be considered a thin layer between the view controllers and the Core Data bits. The advantage is that the UIFetchedResultsController is designed to work with tables. The other advantage is that your least detailed view (the root most likely) can listen as the delegate of the UIFetchedResultsController for changes and update itself.

In this design, however, instead of passing around a context, you would hand off just the entity that the child view controller needs to know about. The Core Data Recipes example provided by Apple illustrates this design quite well.

How does this break rigidity? Each view controller, from the root on down, only knows what is passed into it. The root gets the UIFetchedResultsController passed into it. The child views only get the items it cares about passed into it. None of them care what their parent view controller is. There is no call back to a parent.

Solution two

What happens when we don’t have a typical navigation controller design? Perhaps a child view can pop up a modal view that displays different information. Perhaps a child view, for whatever reason needs to access information that cannot be directly passed into it every time.

In these cases there are a few different options.

View already has a NSManagedObject

Following our example above, lets say that view controller C needs to create a new object. Perhaps it is a detail view of a recipe and the user wants to add a new recipe type (perhaps she is a vegan and just discovered there is no vegan type in the list). In this case we have passed in an entity (the recipe) but not a reference to the NSManagedObjectContext. Fortunately this solution is easy to fix. The NSManagedObject retains a reference to its NSManagedObjectContext internally and we can access it. Therefore we can easily retrieve the NSManagedObjectContext from the NSManagedObject and create the new Type entity and pass it to the modal child or whatever our design calls for.

This again avoids rigidity because the view controller that represents the entity does not need to call up to a parent object or the UIApplication delegate. It is self contained and only manages view controllers that are down stream from it.

View does not have a NSManagedObject

In this situation things are slightly more complicated. In this case we want to create a @property for the NSManagedObjectContext and require that our creator set the property.

@interface MyViewController : ViewController
{
    NSManagedObjectContext *moc;
}

@property (nonatomic, retain) NSManagedObjectContext *moc;

@end

Again, the view controller is an island of its own because it does not care where that NSManagedObjectContext came from. All it knows is that it is required for the view to function. It does not care of it is a new NSManagedObjectContext specifically created for its use (perhaps for a cancelable edit tree) or if it is the same NSManagedObjectContext that has been passed around since the launch of the application. All it knows is that it has the elements it needs to perform its function.

By making the NSManagedObjectContext a settable property we can also transplant the view easily. If, at some point in the project lifecycle, we decide that it makes more sense to have the following design:

Modal View Controller

Taking from Apple’s Recipes Application, perhaps we decide that moving from the table view directly to the image of the recipe is more pleasing to the users and that when they want to see how to make it they can “flip” the image over and see the detail.

Making this change with each view controller being an island is quite simple. We just rearrange the views without having to worry too much about breaking the application.

Solution three

Up until now we have been looking at just a navigation controller design. But what about tab bars? In the situation of a tab bar we again want to avoid rigidity because it is even more common that tabs will get moved around.

The solution to this is to again use a @property for the NSManagedObjectContext and require that the creator set this property before the view is displayed on screen. If you are creating the tabs in code this is trivial because you are already calling init on the view controller and you can add one more line of code after the init to set the property.

If the user interface is being developed mostly in Interface Builder it is slightly more tricky. Personally I am not a fan of creating navigation controllers or tab bar controllers in Interface Builder. However if that is the design then I would recommend referencing the view controllers as properties and passing along the context upon initialization of the application. It may be possible to do this entirely in Interface Builder but I am not comfortable enough to recommend that as a solution.

Conclusion

The overall idea behind this article is to keep each view controller separate from anything up stream or in a different silo. This will make the design far more flexible in the long run. Any time that you feel the “need” to pass in a parent view controller to a child view controller, reconsider the design. Consider using a @protocol delegate design or NSNotification calls instead. Keep each view controller as its own private island.

 
14
Jun
2010
 

Differentiating Tap Counts on iOS [UPDATED]

by Matt Long

In your iPhone/iPad apps you often need to know how many times your user tapped in a view. This can be challenging because, though the user may have tapped twice, you will receive the event and it will look like they tapped once as well as twice. If the user triple-tapped, you will get the event for one tap, two taps, and three taps. It can get a little frustrating, but the trick is timing. You simply have to wait a period of time to see if another tap comes. If it does, you cancel the action spawned by the first tap. If it doesn’t you allow the action to run. There’s a few little nuances to getting it to work, but it can be done. Here is how. (more…)

 
5
Jun
2010
 

Re-Ordering NSFetchedResultsController

by Matt Long

So Marcus is the Core Data guy, but I’ve been working with it a good bit myself lately and was recently faced with having to add re-ordering for a list of entities in a UITableView. The methods I found online for accomplishing this all suggested using an NSMutableArray as the data source for the table view. That will work, but I came up with another method, though similar, that achieved what I need without having to switch from using my NSFetchedResultsController as the data source behind the UITableView. In the end, I did use an NSMutableArray, however, I end up using it just to take advantage of its indexing. Read on to see what I mean. (more…)

 
24
May
2010
 

Fixing the UISplitViewController Template

by Matt Long

The default implementation of the UISplitViewController based template in Xcode does not provide a navigation controller stack in the detail view. Instead it is just a regular old view with a navigation bar at the top. I suppose there are cases when you might want such an implementation, however, i think you would more commonly want there to be a navigation stack for cases when you wan to push new view controllers for your users to see. In this post i intend to demonstrate how to convert the default template to something more useable. (more…)

 
2
May
2010
 

My current Prefix.pch file

by Marcus Zarra

I have posted and discussed this file a few times but as with all things it has been touched, tweaked, and generally improved upon.

In this article we will discuss the latest iteration of my Prefix.pch file. As with anything I post, it is available for you to use as you see fit.

The File

For those who don’t want to read the entire post, here is the file:

1
2
3
4
5
6
7
8
9
10
11
12
#ifdef DEBUG
  #define DLog(...) NSLog(@"%s %@", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
  #define ALog(...) [[NSAssertionHandler currentHandler] handleFailureInFunction:[NSString stringWithCString:__PRETTY_FUNCTION__ encoding:NSUTF8StringEncoding] file:[NSString stringWithCString:__FILE__ encoding:NSUTF8StringEncoding] lineNumber:__LINE__ description:__VA_ARGS__]
#else
  #define DLog(...) do { } while (0)
  #ifndef NS_BLOCK_ASSERTIONS
    #define NS_BLOCK_ASSERTIONS
  #endif
  #define ALog(...) NSLog(@"%s %@", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
#endif
 
#define ZAssert(condition, ...) do { if (!(condition)) { ALog(__VA_ARGS__); }} while(0)

This does not replace the Prefix.pch that comes with your project but it does go at the top of every project that I work on. The rest of this post we will review what this does. (more…)

 
12
Feb
2010
 

Accessing The Cloud From Cocoa Touch

by Matt Long

Everything is moving toward the cloud and unless you’re building calculators, unit converters, or miniature golf score keepers your iPhone app needs to know how to get data from it. In this blog post I intend to demonstrate how to set up a simple server application and how to retrieve data from it and post data to it using Cocoa Touch. I have chosen to use PHP on the server side because of it’s simplicity and ubiquity, and because I’ve know it, somewhat. You should, however, be able to implement something similar using your server side language of choice.

In many cases when you go to access remote data, you do so through a web service API. While services based on such technologies as SOAP or XML-RPC are standards that provide reasonable methods for retrieving and updating data, REST seems to be the methodology gaining the most ground lately. For our purpose in this post I won’t get into great detail of how to implement a REST base web service as, again, REST is not a specific implementation but rather a methodology. (Read up on it elsewhere if you don’t understand what this means). However, I will talk about it briefly so that you can get on the right path for doing your own REST implementation. (more…)

 
23
Dec
2009
 

Automatically save the dSYM files.

by Marcus Zarra

For those not aware, when you compile an Objective-C application, whether it be for the desktop or for Cocoa Touch devices, the debugging symbols are stripped out of the binaries. Therefore, unlike other languages such as Java, when a crash occurs, there is virtually no way to determine where the crash occurred. However, when the applications are compiled, a dSYM bundle is generated. This bundle allows us to match up the debugging symbols with the application’s crash log to help determine the cause of the crash.

(more…)

 
20
Oct
2009
 

Marching Ants With Core Animation

by Matt Long

Marching AntsOur Core Animation book should be available by the end of the year. Go ahead and pre-order it now at Amazon if you would like ;-). When we started writing for Addison-Wesley back in September of 2008, I had no idea how long to expect it to take to finish a technical book as this was my first. One thing I discovered though, is that it is when you are about ready to go to production you start to realize all of the things that you probably should have added to the book, but didn’t think of in time. This blog post will cover one such item as a way to make up for not thinking of it in time. I may include this in a second edition if there is one, but consider this one a freebie. (more…)

 
23
Sep
2009
 

UITableViewCell Dynamic Height

by Matt Long

At first glance setting a height dynamically for table view cells seems a little daunting and the first most obvious answers that come to mind are not necessarily correct. In this post I will show you how to set your table view cell heights dynamically based upon the text content without subclassing UITableViewCell. You can subclass it, however, doing so does not make the code much cleaner as setting the height is done in your delegate for the table view itself rather than the cell anyhow. Read on to see what you need to know to make dynamic cell height sizing a breeze. (more…)