Showing posts with label Objective-C. Show all posts
Showing posts with label Objective-C. Show all posts

Friday, January 13, 2012

UIStoryboard Best Practices

UIStoryboard is a hot topic right now in iOS. However, there have been many misconceptions on the topic. The first reaction to storyboards (what I have seen anyway) is that they are a panacea for all situations. Following that reaction I saw many people claim that storyboards are awful and broken. The truth is, both these ideas are wrong. During WWDC 2011 Apple may have over-promoted storyboards, thus giving the wrong impression and leading to unmet expectations. Let me correct this now: UIStoryboard is not an all-purpose solution, it is another tool for your toolbox.

My intent here is to provide the best practices for UIStoryboard. I will list my lessons learned, but there are probably more yet to learn. I expect over time that this list will expand to include other best practices for UIStoryboard.

Break your storyboard into modules

The first mistake developers have been making with storyboarding is producing large, monolithic storyboards. A single storyboard may be suitable for small apps but certainly not for large apps. Don't forget one of the key principles of programming and abstraction: decomposition. We decompose our code into modules to make them more reusable and reduce maintenance costs. The same is true for user interfaces, and it applies whether you are using UIStoryboards, XIBs, or anything else. There is an even deeper principle wanting to emerge: when code and user interfaces are decomposed together, then you have truly useful and reusable code, user interfaces, and products (you can quote me on this).

The first question to ask is "how do I identify the natural modules of my app?" Let's start with something easy. Many apps are based on a tab bar controller. Each tab is a natural module and you hence you can put them in their own storyboard. Next, if you have two tabs (or any two views for that matter) with a segue to a common view, then that common view (and its following hierarchy) is almost certainly another natural module. Once you have pruned your view hierarchy, you will probably find that each module can be given a name. For example, you may have your login storyboard, settings storyboard, about storyboard, main storyboard, etc. If you can give a fitting name to each module, then you have decomposed your hierarchy well.

Keep in mind that having a single view in a storyboard is not a bad thing. This is particularly true with table views. The power of static and prototype table view cells is very useful.

You should also note that breaking storyboards into modules makes them more friendly to version control and sharing among a team.

You don't need to convert everything at once

When you first saw storyboards, you may have had an urge to convert everything over to UIStoryboard. I know I did. Be aware that this does take time and you may not gain any immediate benefits from switching everything. Fortunately, you don't need to do it all at once. You can switch over the parts of your app that will benefit the most now. Then over time you can slowly switch out others.

Make custom UITableViewCell subclasses for prototype cells

Probably the best feature of UIStoryboard is prototype cells. They make custom table view cells easy. Prototype cells can be easily customized; however, the UITableViewCell class may not specify the IBOutlets you need. A custom subclass also gives you another advantage. You can create a -setupWith<#Object#>: method. This takes your setup code out of your table view controller and into the cell itself. This is where you can gain some great reuse.

Not only can you create custom UITableViewCell subclasses, but you can have one subclass service many prototype cells. For example, you may have a cell that takes a Person object. In one table view your cell may have main label on the left and a detail label on the right. A different table view may use the same cell but have a main label above and a detail label below. Your cell subclass handles the content, but the prototype cell handles the look and feel. Again we gain great reuse and flexibility by decomposing code and views together.

Don't forget about IBAction, IBOutlet, and IBOutletCollection

Segues are nice and can do a lot, but don't forget about the other IB fundamentals. Segues can't cross storyboards, but IBActions can. IBActions can also clean up an unnecessary spaghetti segue mess and reduce the need for custom segues. Everything has their place and their use; they are all tools at your disposal.

While on the topic of IBActions and family, I should cover encapsulation. Most, if not all, your actions and outlets do not need to be public. So, rather than put them in your public headers, put them in a class extension. See here for more details. Xcode/Interface Builder didn't handle this well in the past but now there are no problems. This keeps your interfaces much cleaner and easier for others to understand.

Don't forget about XIBs

Even though storyboards are very similar to XIBs, they still have a place. Simple, one-view modules may be better represented as XIBs. Also, XIBs can hold custom views without an associated view controller. UIStoryboard requires that view controllers be the basic unit.

You don't need to have a main storyboard

You may have noticed your app settings now has a "Main Storyboard" setting. To use UIStoryboard you are not required to use this. In fact, my latest project has neither a main storyboard nor a main XIB. It uses a programmatic UITabBarController. From there I load all my tab storyboards. The beauty of it all is that it doesn't matter whether I use UIStoryboards, XIBs, or code. All three options are flexible enough to work with each other in any combination.

Specify the name of your app delegate in main.m

As I mentioned the other day, you may need to change your main.m file if it doesn't specify your app delegate's name. It should look something like this:

UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class]))

Put your storyboards in a category

To get one of your storyboards, you need to call +storyboardWithName:bundle:. Be wary any time you need to hard code a string for a key, especially one that can change frequently. Should you ever need to rename your storyboard, you will have to change all references to that storyboard. My favorite way to handle this is with a category. It looks something like this:

@implementation UIStoryboard (MyApp)

+ (UIStoryboard *)mainStoryboard {
    return [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
}

@end

The benefit of the category approach is that if you ever rename a storyboard, you only need to change the hard coded string in one place. It also makes your code more readable.

Summary

If you take anything from this post you should remember these:
  1. Decompose your code and your views.
  2. UIStoryboard is a great tool, but it's not the only tool.
I hope these tips and best practices help promote proper use of UIStoryboard. I invite all my readers to let me know of other best practices they encounter.

Thursday, December 15, 2011

Migrating to UIStoryboard

I’ve just recently started using UIStoryboard and so far I’ve been very pleased with it. Building the UI is faster, easier, and requires less code. It’s also immensely helpful to get a bird’s eye view of your full workflow. However, when migrating an old app from using regular XIBs to UIStoryboard I did encounter some troubles. When launching the app, I would get the following error messages:

“The app delegate must implement the window property if it wants to use a main storyboard file.”
and
“Applications are expected to have a root view controller at the end of application launch.”

I could clearly see that my app delegate was implementing the window property as expected. Fortunately, StackOverflow came to the rescue. It turns out that main.m needs to be modified when switching to UIStoryboard from XIBs (in older projects). The change looks like this:

// Old main.m
UIApplicationMain(argc, argv, nil, nil);

// New main.m
UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class]));

The documentation for this parameter reads:

The name of the class from which the application delegate is instantiated. If principalClassName designates a subclass of UIApplication, you may designate the subclass as the delegate; the subclass instance receives the application-delegate messages. Specify nil if you load the delegate object from your application’s main nib file.

Basically, if you aren’t using XIBs, you must let UIApplication know what your app delegate’s name is. You will also notice that any new projects created with the latest version of Xcode will specify the app delegate, even if you are using XIBs. This prevents any problems should you migrate to UIStoryboard later.

UIColor Category

For a long time I’ve wanted more convenience methods for UIColor. The set Apple provides is a nice starting point but I often find myself wanting more. In particular, the Mac color picker has a crayon box color picker with common colors. Sadly, there are no convenience methods for these colors. Since I use them so frequently, I decided to put them all in a category. This was tedious work since I had to do them one-by-one by hand.

After getting these 48 convenience methods I figured why stop there. I moved on to the HTML colors. At the time I didn’t realize how many standard HTML colors exist (147). After seeing that number I almost threw out the idea, but I remembered that @alesplin taught how to use Vim macros in the November BYU CocoaHeads meeting. Using a list of HTML colors and their associated hex values, I had all 147 HTML color convenience methods finished within minutes. Vim may be an old, crusty text editor, but its macro editing power is unmatched by modern IDEs.

If you want a copy of my UIColor category, you can find it in my RBCategories repo on Github.

Tuesday, August 23, 2011

iOS Recipes Review

Here’s a book I couldn’t recommend more. iOS Recipes by Paul Warren and Matt Drance has done more to improve my code than any other book.

Summary

iOS Recipes gives 40 code samples to improve common or useful iOS code. The recipes are grouped into five categories: UI, Table/Scroll Views, Graphics, Networking, and Runtime. The book is organized so you can read it in whatever order suits your needs. The wide range of recipes guarantees there is something that will benefit you.

Pros

iOS Recipes includes many code samples that can be dropped into any project and will just work without any extra modification. Any project could benefit from using at least one of the included recipes. For example, the common table view cell production/customization process typically takes 20+ lines of code. I now write the same code in 3 lines of code and it is fully Interface Builder customizable.

The greatest value of this book, however, is the explanation of how these recipes were designed. Warren and Drance explain exactly why they, for example, chose blocks over delegation or vice versa. By applying their same reasoning to other code, you can create your own quality recipes. This is further encouraged by not giving recipes that do everything. Some extensions are left as an exercise to the reader.

Cons

There’s nothing I can say against this book. It really is a great book.

Recommendation

Every experienced iOS developer should own this book. By following the principles taught in iOS Recipes, your code will increase in quality. I also recommend this book to any daring, young developers who are interested in gaining a deeper understanding of the full power of Objective-C and designing quality code.

Tuesday, August 2, 2011

Objective-C @property Best Practices

Now for my next rant on poor Objective-C code. Coming from other languages it's understandable that most developers don't take full advantage of the power of Objective-C 2.0. Here's a practice I hope that becomes more widespread.

Use @property

One feature of Objective-C that is underutilized is @property. The Objective-C compiler can write so much code for us, we just have to let it. Note that some of what I'm going to cover only works on the 64-bit (modern) Objective-C runtime. However, you probably won't find any situation where you need to write code for the 32-bit (legacy) runtime. The only reason we wrote legacy runtime code was because that’s what the iOS simulator used to run on (prior to iOS 4.0). That was fixed over a year ago.

Clean up your Headers

First, let's use @property to clean up our header files. The first thing to do is delete all of your ivars. Yes, delete all of them. They are no longer necessary. @synthesize will not only make your getters and setters, but it will also make your ivars. This was one of the major changes from the legacy to modern runtimes. This is nice because we don't need to be redundant about our instance variables anymore. Now, for all of your public ivars, make an equivalent @property. We'll handle the private and protected ivars in a moment. With just your public @propertys, your headers will now be much shorter and easier to read. Remember, headers are for public information. That is the whole idea behind encapsulation. You don't want your private information in your public headers. Even though I'm focusing on @propertys, you can apply the same ideas to methods too.

Categories and Class Extensions

Before handling your private and protected ivars, you need to understand categories and class extensions. If you feel comfortable using class extensions, feel free to jump to the next section.

A category is a way to extend the interface and functionality of an existing class. You declare them similarly to regular classes:

// MyClassAdditions.h

#import "MyClass.h"

@interface MyClass (CategoryName)

// Extra method declarations.

@end


// MyClassAdditions.m

#import "MyClassAdditions.h"

@implementation MyClass (CategoryName)

// Extra method implementations.

@end

Making a category is that simple. You just need to remember to #import your category when you want to use your extra methods. Class extensions, for all intents and purposes, are categories. The main differences are that only the original class can create a class extension for itself and you can declare @propertys in a class extension. So we will do just that. To create a class extension you simply create a category with no name. It will look something like this:

// MyClass.m

@interface MyClass ()

@property (nonatomic, copy) NSString * myPrivateString;

@end

With your class extension in place, you just need an associated @synthesize myPrivateString; and you're done. It's that simple. You can do this with all of your private class variables with no problems.

Protected Data

Now we are left with the protected variables. These are a little more tricky. Technically protected variables and methods don't exist with this technique. Then again “private” technically doesn't exist at all in Objective-C. The runtime won't stop you from calling private methods. Anyway, you should avoid protected data as often as possible. Sometimes that just isn't possible though. If you want a protected @property, just put it in your class extension like your private data. Then, any subclasses that need to access the protected property need to contain an identical @property in their class extensions. You will want to include some documentation about your protected @property. This does seem a little redundant to have identical @propertys, but it's bearable since Objective-C generates the important code for you. Again, this also works for methods. This is particularly nice because the @protected key word doesn't work on methods like it does ivars. One thing to note is that you can't call super in a protected method using this technique (you will get an annoying warning). If you need to make a super call, then your protected method should be placed in a private header instead. This private header should contain just the prototypes and is ONLY imported by classes that need that information.

Readonly Getters

What about when you want to make a public getter but a private setter? Objective-C can do this for you too. In your public header you can do something like this:

@property (nonatomic, copy, readonly) NSString * myPrivateString;

Then in your class extension you make a similar declaration:

@property (nonatomic, copy, readwrite) NSString * myPrivateString;

You just need to make sure the two declarations mirror each other (i.e. nonatomic and nonatomic, retain and retain, copy and copy, etc.). From there you just use @synthesize and Objective-C takes care of the rest.

Other @property Modifiers

While speaking of @property modifiers, I should take a moment to discuss them for anyone unfamiliar. You may skip to the next section if you already know the modifiers. By default an @property is atomic, assign (or weak), and readwrite. I've never found a good reason for atomic. Atomic just means that Objective-C is going to use a lock to enforce thread safety. This will make your getters and setters slower since it has to acquire and release the lock. If you are using single-threaded code this is completely unnecessary. If you are using multi-threaded code, you really should be using Grand Central Dispatch (or NSOperationQueue) to take advantage of lockless exclusion.

The next modifier is copy/retain/assign. For almost everything you do, you will use retain. It's good to know the exceptions though. When you have an NSString, NSArray, NSSet, or other object with mutable/immutable variants, you should use copy instead. If the object is immutable, it will be retained for efficiency, otherwise it will be copied.

Assign (or weak when using ARC) also has some uses. Mostly you will use it when dealing with primitives, such as BOOL or int. Since they aren't objects you can't call -copy or -retain on them. You will also use assign when you have want to avoid a retain cycle by creating a weak relationship. This is common with delegates.

You can also specify the names of your getters and setters. You specify getter=myGetterName or setter=mySetterName. This is often used with BOOLs. For example, you may create a property like this:

@property (nonatomic, assign, getter=isOn) BOOL on;

Dealloc

When writing your -dealloc methods, you may wonder how you can release your instance data without direct access to your ivars. There is only one reasonable way to do this. You should call [self setMyProperty:nil];. This will set your ivar to nil and consequently release the old value.

Exceptions

All rules have their exceptions including @property. If you need to make a custom getter or setter, you will need to create an associated ivar. Technically you can actually access synthesized ivars directly. However, Apple considers this to be a “bug” and access to synthesized ivars may disappear in the future. You can add ivars to class extensions for your private properties. Be aware, though, this is only supported on Clang/modern runtime and may require additional settings.

Benefits

Now that we've gone over all that, let's go over the benefits of these extra techniques:

1. The obvious benefit is the compiler will write your getters and setters for you. The compiler not only writes your getters and setters but also makes them Key-Value Observing (KVO) compliant. This means you can observe the changes of any property on an object. KVO is especially useful when writing Model View Controller (MVC) code. Controllers can watch model objects for any changes and update the views as appropriate.

2. You will have less memory bugs. When writing your actual code, you should always use your getters and setters instead of accessing ivars directly. This will make most of your memory management bugs disappear instantly. You won't need to remember to call retain/copy and release with your ivars. Your synthesized getters and setters will do that automatically for you.

3. Your code will be better encapsulated. I've seen too much code where I've had to guess which ivars (and methods) I could safely use due to a lack of organization and no documentation.

4. Last, but not least, your code will be more readable. Your headers won't be cluttered with private and protected data, and your implementation files won't be cluttered with standard getters and setters. Furthermore, your files will be better organized. You will know exactly where to find your public, private, and protected data.

Employ these techniques and they will serve you well. Other people who have to use your code after you with thank you too.

Credits

The ideas in this article were strongly influenced by the Apple docs, iOS Recipes Recipe 35, various WWDC videos, and a lot of personal experience (i.e. bugs).

----
Update: August 23, 2011

I have further refined and corrected this article through further study and experience on the topic, particularly ivars and custom accessors.

Saturday, July 30, 2011

One singleton to rule them all

One of the most common design patterns is the singleton. However, implementing singletons, especially in Objective-C, can be very repetitive. I often forget how to properly override all the memory management methods and need to look up a previous singleton. One of the goals of programming is to automate the repetetive, mundane tasks. Cocoa With Love has a great synthesized singleton made from a C pre-processor macro. The problem with this is that it's not flexible. So, I made an Objective-C singleton that can be dropped in any project. By subclassing RBSingleton you can gain all the benefits of a singleton without adding any further code and you have full flexibility to customize each subclass.

There are two main parts that make RBSingleton possible. First, it stores all the singleton instances in a class-wide dictionary. A singleton typically keeps a static pointer to the singleton instance. This works fine as long as it's not subclassed. When subclasses become involved, the subclass that allocates first defines the singleton instance for all subclasses. This restriction is normally beneficial to singletons, but breaks with subclassing. I could have required subclasses to provide a pointer to a static class pointer through a method call, but this imposes more on the subclass's implementation than I wanted. By using a class-wide dictionary, every subclass can store its singleton instance under a unique key. To guarantee a unique key, I simply use the subclass's name.

Second, the singleton instance is allocated by dynamically calling NSObject's -allocWithZone: method as shown below.

Method allocMethod = class_getClassMethod([NSObject class], @selector(allocWithZone:));
sharedInstance = [
method_invoke(self, allocMethod, nil) initialize];

The trick here was to allocate the singleton as the class of the RBSingleton subclass but use NSObject's -allocWithZone: method to do so. This is similar to calling [super allocWIthZone:nil];. The difference is that it's jumping more than one level in the inheritance hierarchy. This is known as a grandsuper call. The Objective-C dynamic runtime makes it possible to make such a call. You will also notice that I hardcoded [NSObject class] into the code. I could have dynamically discovered the root class with the following code:

+ (Class)rootClass {

        
Class rootClass = nil;
        
Class currentClass = [self class];

        
while ((currentClass = class_getSuperclass(currentClass)))
                rootClass = currentClass;

        
return rootClass;
}


If I instead needed to get a grandsuper class that isn't necessarily the root class and I know a subclass of the grandsuper I could use simpler code like this:

[RBSingleton superclass];

Since I know the specific grandsuper class I need, I hardcoded it for efficiency. If you use RBSingleton and find a need to dynamically discover a particular grandsuper class, you can use the above code to do so. I've uploaded RBSingleton as a Gist and you can find it here.

One last note, to use RBSingleton you need to include libobjc.dylib for the dynamic runtime calls.

Tuesday, July 26, 2011

#define Abuse

Lately I've been encountering some terrible Objective-C code, and I have a few words to say about it. One of the first problems I've found is the overuse of #define. Don't get me wrong, #define has its place, but when it comes to constants #define should not be the first choice.

Anti-Patterns
One of the problems with #define is that it's simply a macro substitution. There is generally no type associated with the value. This makes is harder for the compiler to warn you of potential errors. Macros can also have side effects you may forget about. For example:

#define MY_STRING_CONSTANT [[NSString alloc] initWithFormat:@"Hello World!"] // Very bad.

The above example will cause a memory leak unless you remember to release the value each time. Just a side note, Apple's static analyzer will pick up this error if you turn it on. I should also mention that the following, related example is not preferable. I have actually seen this used in production code before.

#define MY_STRING_CONSTANT [NSString stringWithFormat:@"Hello World!"] // Still not great.

Numbers
With a couple anti-patterns out of the way, let's go over the proper way to define constants. You will find that it doesn't take much more effort to properly define constants. Numbers are the simplest and one of the most common, so we'll start with them. In your .m file (applies to .c or .cpp too) you will define your constant like the following:

const NSInteger kMyInt = -100;
const NSUInteger kMyUnsignedInt = 42;
const CGFloat kMyFloat = 3.14;

You could instead use 'int', 'unsigned int', and 'float' if you prefer, but the above types are generally the preferred data types. If you want to keep your constant visible to just your implementation file, then you are done. If not, you need to do one last thing. In your header file, you will need to use the following:

extern const NSInteger kMyInt;
extern const NSUInteger kMyUnsignedInt;
extern const CGFloat kMyFloat;

The reserved word 'extern' makes a promise to the compiler. You are letting the compiler know that you are not defining the value right away, but at link time, that value will exist. In this case, it's defined in your implementation file. With that in place, you are now done; your constant is defined and other classes can #import (#include for C and C++) your header file and use your number constants.

You may wonder why you can't define the constant right in your header file. If you do, you will get an error message that looks like this: "ld: duplicate symbol <Constant Name> in <File 1> and <File 2>." Generally #import handles duplicate imports properly; however, it doesn't work for constants. I figure this error is why developers unaware of 'extern' default to #define.

Enumerations
Closely related to numbers are enumerations. If you ever have a series of related number constants, you probably want an enum. For example:

// A contrived example but should get the idea across.
enum {
        kJanuary = 1,
        kFebruary = 2,
        kMarch = 3,
        kApril = 4,
        kMay = 5,
        kJune = 6,
        kJuly = 7,
        kAugust = 8,
        kSeptember = 9,
        kOctober = 10,
        kNovember = 11,
        kDecember = 12,
};

Enumerations are great for bit masks too.

// Another contrived example.
enum {
        kBit1 = 1 << 0,
        kBit2 = 1 << 1,
        kBit3 = 1 << 2,
        kBit4 = 1 << 3,
};

Enumerations are where type checking really helps. Say you are using a switch statement, the compiler can warn you if you didn't include one of your enum values as a switch case.

Strings
Strings are also very common in Cocoa programming. There is one extra detail that makes them different from numbers. At first you may want to make a constant like this:

const NSString * kMyString = @"Hello World!"; // Wrong - String Anti-Pattern 1

This is wrong for a couple different reasons. First, NSString is immutable, meaning that it can't be changed. This essentially makes it a constant by default. However, there is a big flaw with the above anti-pattern. I will first show the proper way:

NSString * const kMyString = @"Hello World!"; // Right

At first glance, you are probably wondering why 'const' is next to the constant name. The difference between the number and string examples is that the NSString is a pointer. The first string example tells the system that the value @"Hello World!" can't change, but the pointer value can change. You probably wouldn't, but you could do the following:

kMyString = @"Goodbye World!"; // Very bad, but allowed in String Anti-Pattern 1.

You didn't change the value of @"Hello World!", but you did change what kMyString pointed to. That doesn't sound like a constant at all.

By the way, the following is also permissible, but wrong.

const NSString * const kMyString = @"Hello World!"; // Wrong - String Anti-Pattern 2

This makes both the value and the pointer constant. However, the first 'const' changes the data type of the constants. None of the Cocoa frameworks accept a const NSString * (since it's redundant). This means that you will have a compiler warning anytime you try to pass your constant to a Cocoa framework method. You might do something similar with other objects, but in Objective-C, such cases should be very rare. This is something more common in C or C++.

Objects
Objects other than strings can be a little more tricky. You can't do the following:

MyObject * const kObject = [[MyObject alloc] init]; // Wrong - Object Anti-Pattern 1

The problems is the right-hand side does not evaluate to a compile time constant. Furthermore, if it was possible, it would be difficult to configure the object properly. This requires a different technique.

// Right
+ (MyObject *)MyConstObject {

        static MyObject * obj = nil;

        if (!obj) {
                obj = [[MyObject alloc] init];

        // Any other initial setup.
        }

        return obj;
}

Looking at the return type of MyObject *, you may think this has the same problem that String Anti-Pattern 1 had. This is not the case here. The original constant pointer is protected within the method; it can't be changed externally. When you call the method, you receive a copy of the object's address. You can change it if you want, but it won't affect anyone else. Naively you may want to change the return type to MyObject * const, but a const pointer doesn't affect the data type. You could do the following regardless:

MyObject * obj = [[self class] MyConstObject]; // Type MyObject * is the same as MyObject * const

One last note about object constants is that they are technically memory leaks. However, they are permissible for the same reason that singletons are permissible. What's more interesting is that Apple's latest static analyzer now flags singletons as memory leaks but still doesn't catch the above constant.

When to use #define
I should probably include a kind word about #define. If you want to use any pre-processor macros such as #if or #ifdef, then #define is your only choice. #define is also good for simple, inline functions or when you want to write some code that will do automatic renaming (see Cocoa With Love's synthesized singleton). #define has countless valuable uses, but when it comes to constants, try something else first.

Friday, June 3, 2011

Key-Value Validation

Along with all the other features of Key-Value Coding, there are methods in the API for validating the properties of an object. These methods are known as Key-Value Validation (KVV). The format for a validation method is -(BOOL)validate<Key>:(id*)error: (NSError**) where “Key” is the name of the property to validate. You must be sure to spell the property name properly, otherwise the validator may not be called properly. When calling a validator, you have two choices. First you can call the validator directly. Second, you can call -(BOOL)validateValue:(id*)forKey:(NSString*)error:(NSError**). The second choice will infer the name of the validator method, which is why it is important to spell the method name properly.

The following gives a simple template of how to implement a validator. This template may be copied directly into Xcode.

- (BOOL)validate<#Key#>:(id *)ioValue error:(NSError **)outError {
        
        if (<#Value is not valid#>) {

                // Try to coerce the value into a valid value.
                // The coerced value must be autoreleased.
                *ioValue = <#Some valid value#>;

                if (<#Value cannot be coerced#>) {
                        
                        if (error != NULL) {
                                
                                // Create an error object.
                                // Merge errors if necessary.
                        }

                        return NO;
                }
        }

        return YES;
}

Implementing validators has several gotchas to watch for. One of the things to notice is the value being passed in for validation is of type id*. This means that you can return a new value by reference. For example, if you want to ensure that a name is unique, you can use the validator to append a number to the name to coerce it to be unique.

Coercing a value has some critical memory management issues. The value passed in for validation must be autoreleased, and a coerced value, if any, must likewise be autoreleased. Furthermore, if you do return a coerced value it must be return a new value rather than modifying the old value, even if the old value is mutable.

When implementing a validator you must never call -set<Key> within the validator. The validator is responsible for validating, not setting.

Primitives cannot be validated since the validators expect an object. However, you may wrap the primitive value in an NSValue or NSNumber object.

Another gotcha to note is that validators are not called automatically. It is up to your discretion when you want your objects to be validated. When calling a validator, there is a general form to follow as shown below:

// Note that the value is autoreleased.
NSString * someName = [[[NSString alloc] initWithFormat”@“Timmy”] autorelease];
NSError * error = nil;

if ([obj validateName:&someName error:&error) {
        
        // The setter is called since the value could have been coerced and to properly retain the value.
        [obj setName:someName];
}
else {
        // Report an error to the user or whatever else you want.
}

Aside from the above template, you could validate the parameters of your Objective-C setters by using NSParameterAssert([obj validateValue:&someValue forKey:@“someKey” error:NULL]). This is good for debugging since asserts can be disabled by defining NS_BLOCK_ASSERTIONS.

Core Data extends the ability of KVV. Although KVC does not automatically call validation methods, Core Data provides three points which validators can be called automatically. These methods are -(BOOL)validateForInsert:(NSError**), -(BOOL)validateForUpdate:(NSError**), and -(BOOL)validateForDelete:(NSError**). These methods are called when an NSManagedObject is inserted into a managed object context, updated, or deleted, respectively. You may override these methods in your subclasses of NSManagedObject to call your validators. Additionally, you may perform inter-property validation here. There may be instances where certain combinations of values are incorrect. For example, in a family tree, it is incorrect to set a female person as someone’s father.

When using the Core Data validation methods, you must be careful to not recursively dirty the managed object context. Dirtying the MOC can be done in numerous ways such as coercing property values on every validation request. If you do recursively dirty the MOC, then you will get a message like this: ‘Failed to process pending changes before save. The context is still dirty after 100 attempts. Typically this recursive dirtying is caused by a bad validation method, -willSave, or notification handler.’ If you face this situation, you will either need to find another way to implement your validator or don’t have your validator called automatically. If you opt to not call your validator automatically, then you will probably want to call your validator anytime you try to set the associated property.

In order to avoid your validators from being called automatically you have a few options. You could avoid calling NSManagedObject’s -validateForX: methods (where ‘X’ is ‘Insert’, ‘Update’, or ‘Delete’) by not calling [super validateForX:&error]. However, this may not be wise since NSManagedObject may do more than call each of the validators. You could instead try having your object reject one or more validation messages from itself. The easiest and best option is to make a validator that is not KVC-compliant. In other words, name the validator method so it doesn’t match with a property name.

When using the Core Data validation methods, you may have multiple errors occur. You have two options to handle this. First, you can return the first error as soon as it is reached. Second, you can merge the errors into a single error with error code NSValidationMultipleErrorsError.

KVV is very useful, especially for Core Data. I’m surprised it isn’t used more frequently. However, Core Data does automatically generate some basic KVV methods from the MOM file. Hopefully, this tutorial will increase the custom usage of KVV.

Friday, April 29, 2011

Delegates and Memory Management

The iOS SDK uses the delegate pattern everywhere. Occasionally, you may want to create your own delegate protocol for some custom object. When doing so, keep in mind the subtleties of memory management. Always use @property (nonatomic, assign) rather than @property (nonatomic, retain) with delegates. It is often habit to use “retain,” but a delegate must use “assign.”

Consider the following scenario. When creating an object, its delegate is often set to “self.” Using retain as the setter policy will cause the object to retain itself. The problem is that objects (usually) don’t ever call release on delegates. Hypothetically, if a delegate is released, it’s likely to be done in -dealloc. Since the object retained itself, -dealloc will never be called. The result is a memory leak. Xcode’s static analyzer will not be able to catch this type of leak. One of the major pitfalls of reference counting is circular dependencies. The only solutions in iOS are to avoid such dependencies or force the cycle to be broken somewhere. The first option is highly preferred.

By using assign, we avoid a circular dependency. However, this doesn’t mean we can’t retain a delegate if needed. It just has to be done manually. For example: [self setDelegate:[aDelegate retain]];. This also means that the release must be done manually. Typically this can be done in -dealloc. Additionally, you may want to include a check for delegate != self. Sending [self release] in -dealloc will result in an infinite loop.

Thursday, August 26, 2010

Raster Map Overlays for iPhone

The release of iOS 4.0 included the ability to add custom image overlays to maps. I recently took advantage of this in FastTrac. Previously, FastTrac was using OpenGL to handle the map. This worked well but required an unreasonable amount of memory. It also wasn’t easy to maintain. Changing to a map overlay fixed both problems. Session 127 of WWDC10 covered briefly how to implement such a map. Some sample code is also available to all developers that makes the process much easier. This session gives a good overview, but is missing some of the fine details. It is my intent to fill in the gaps. I will start with my own overview.

  1. Download and install GDAL (available at gdal.org)
  2. Download the TileMap sample project.
  3. Get the coordinates of your image’s bounding rect.
  4. Generate a .vrt file.
  5. Generate the mercator projected map tiles.
  6. Add the tiles to the sample project.
First, download and install Geospatial Data Abstraction Library (GDAL). This can be found at gdal.org. It can also be installed with MacPorts by using “sudo port install gdal”. Make sure you set your PATH variable properly. I won’t go into any details of how to do this. This shouldn’t be hard.

Next, download the TileMap sample project. This is available to all iOS developers through the WWDC10 website http://developer.apple.com/videos/wwdc/2010/. The sample code can be hard to find. It’s on the iTunes page where you download WWDC10 session videos. Between GDAL and this sample project, you as a developer won’t need to do much to get your map working.

This is where things get interesting. You will need to find the coordinates of the bounding rect of your image to overlay. Google Earth makes this easy. I got this tip from a fellow developer on the Apple developer forums. First, find the area you want to place the image overlay. Next, right click on ‘My Places’ (it’s on the left column). Select Add > Image Overlay. This will open a pop up window. From here you can open your image, change the opacity, and move/resize your image. Make your image transparent enough to see both your image and the underlying map. Once you have adjusted your image to match, click on the ‘Location’ tab. There you will find your latitudes/longitudes. You will need to convert those to a decimal value. A quick Google search will turn up a tool to make that conversion for you.

Now to put GDAL to work. The first part is to generate a .vrt (virtual raster) file. This is probably the hardest part of the process. It’s very easy to make a mistake. You will use gdal_translate to map your corner pixels to the coordinates you just found. The terminal command is as follows:

gdal_translate -of VRT -a_srs EPSG:4326 \
-gcp x1 y1 long1 lat1 \
-gcp x2 y2 long2 lat2 \
-gcp x3 y3 long3 lat3 \
-gcp x4 y4 long4 lat4 \
image.jpg image.vrt

There are a few things to note. First, your map image doesn’t have to be .jpg. Several formats are supported. Also, be very careful with your coordinates. Small errors make big problems. Notice that longitude comes first. I had them backwards and spent two days trying to figure out why it wouldn’t work. As for the x and y values, these are your pixel coordinates. (0,0) is the top left of the image.

If you have done everything correctly, the rest is easy. gdal2tiles.py will take your .vrt file and image overlay and generate mercator projected map tiles. The command is simple - “gdal2tiles.py -p mercator image.vrt.” You only need to give it the .vrt file. The .vrt file keeps a relative path to the image overlay. gdal2tiles.py will generate your map tiles along with other various files. If you don’t want these extra files there are command line options to skip them.

With your new map tiles, you simply need to add them to the TileMap project. First, delete the old tiles in the sample. Make sure they are deleted both in XCode and the source directory. If you have previously run the app, you may need to delete the app from your device/simulator. Next, copy your map tiles into your project. When copying your files, there is a vital gotcha to watch out for. You will need to create folder references instead of groups (see image below). Folder references will appear as a blue folder icon, whereas groups appear as a yellow folder icon. The reason for this is because the code is dependent on not just the files but also the directory structure.



If you named your map tiles directory any other than “Tiles,” you will need to change the code to use your directory instead. Finally, run the app and everything should work. If there is a problem, it likely occurred while generating your .vrt file.

Friday, August 13, 2010

Using a UITextField in a UIAlertView

In an app I have been working on, FastTrac WT, there is a UIAlertView with a UITextField added as a subview. Anytime the alert view was dismissed, the error “wait_fences: failed to receive reply:” would show up. It doesn’t make much sense without knowing what the problem is. That seems to be the irony of error messages. The problem turns out to be that the text field must resign its first responder status before it is released. Knowing this the error message makes more sense. The system couldn’t get a reply from the first responder. The solution to this is to resign the first responder status in the alertView:didDismissWithButtonIndex: method. Using it here makes a smooth animation. The alert view will be dismissed followed by the keyboard. An alternative is to resign the first responder status in alertView:willDismissWithButtonIndex:. The alert view and the keyboard will be dismissed at the same time and the alert view will fade and move downwards with the keyboard. This animation also looks nice and the transition is faster. However, resigning the first responder status in alertView:didDismissWithButtonIndex: does not create a smooth animation. The keyboard is dismissed before the alert view. This creates a sudden jump as the alert view re-centers itself to the viewable area. Either of the first two methods are good candidates for fixing this error. Try both and judge which animation fits best with your app.

Thursday, June 3, 2010

Action Sheet Won't Cancel

Here’s another little problem that has perplexed me for some time. I noticed that when using a UIActionSheet, sometimes the cancel button appears to be unresponsive. Typically it must be tapped several times before dismissing the action sheet. I finally decided to take a look around stackoverflow to see if anyone else has noticed such behavior. I found exactly the answer I was looking for. The problem is that I was using a UITableView in a UITabBarController. When I was displaying the action sheet, I was showing it from the table view. By doing this, only the top most part of the cancel button works. This is because the hit testing won’t work properly. The system will think that we are tapping on the tab bar rather than the action sheet. This is fixed by changing one line of code. Rather than use the usual
[actionSheet showInView:self.view];
instead use
[actionSheet showInView:self.parentViewController.tabBarController.view];
This will show the action sheet from the tab bar controller and hit testing will work as expected.

Saturday, May 15, 2010

Twitter Integration

I previously wrote about Facebook Connect. However, Facebook is not the only social network out there. Twitter is another popular network.

The implementation process is similar to Facebook Connect. I will list the steps:
  1. Register your app with Twitter.
  2. Download and copy MGTwitterEngine into your source code.
  3. Create an MGTwitterEngineDelegate and an MGTwitterEngine object.
  4. Create your own login page for Twitter.
  5. Pass the user’s credentials to MGTwitterEngine.
  6. Authenticate the user’s credentials.
  7. Start tweeting!
To start, you will need to register your app with Twitter. This can be done at http://dev.twitter.com/. This is also where you will find all of the API documentation and other information. Unlike Facebook, only one user can be a developer for a particular app. So, you may want to create a Twitter account specific to your app or company to handle the development of your Twitter features.

Another point to note is that after June 30, 2010 your app will have to use OAuth (or xAuth) for authentication. I won’t go into the details here. Consult the Twitter documentation for details.

Now you can start implementing Twitter into your app. Unfortunately, Twitter doesn’t have a convenient Xcode project to use. This will require using some third-party software. I used MGTwitterEngine. It is produced by @mattgemmell. His code can be found at http://mattgemmell.com/.

MGTwitterEngine revolves around the use of the MGTwitterEngine object. This isn’t nearly as advanced as Facebook Connect. You will have to handle the login dialog and automatic re-login on your own. A user’s credentials can be securely stored in the iPhone’s keychain. Details on the keychain can be found in the iPhone API.

Logging in takes several steps. You will first need to create an MGTwitterEngineDelegate before creating an MGTwitterEngine object. Once you have prompted the user for their user name and password, this can be passed on to MGTwitterEngine by the following method:
[twitterEngine setUsername:(NSString *)name password:(NSString *)password];
However, this does not authenticate the user name and password. It simply stores them in the MGTwitterEngine. Verification can be received by calling:
[twitterEngine checkUserCredentials];
This will make a call to the API to verify the user’s credentials. This method does not wait for the verification to return. Instead, one of two MGTwitterEngineDelegate methods will be called when the verification returns. These two delegate methods are:
- (void) requestSucceeded:(NSString *)requestIdentifier
- (void) requestFailed:(NSString *)requestIdentifier withError:(NSError *)error

Since these calls occur asynchronously, you will need to handle this accordingly. Some options include blocks, GCD, and/or how ever else you want to handle it.

From here you are ready to start using Twitter from your app. MGTwitterEngine provides several methods for doing various actions. One you will likely use is
[twitterEngine sendUpdate:@“Hello World!”];
This will send a tweet as you would expect. Remember to keep tweets to 140 characters.

Your now ready to make Twitter a part of your apps. Happy Tweeting!

Friday, May 14, 2010

Facebook Connect

UPDATE: This post was written for the Facebook REST API. The REST API is now deprecated and you should use the Graph API instead. I may write a new post on the Graph API in the future.

This time I’m returning to a topic I learned months ago - Facebook Connect. However, I need a refresher on it. One of the great luxuries of programming is adding functionality without writing the code personally. Fortunately, Facebook has created an API that works well on a multitude of platforms. With this API, an iPhone app can become more interactive as users share with others what they are doing with it. This also results in an app receiving greater visibility to the public.

Anyway, several months ago I added Facebook and Twitter support to Police Scanner 2. My biggest struggle with implementing Facebook support was that the iPhone documentation is very minimal and not as explicit as I would like. I figured out almost everything simply by trial and error. Hopefully this blog post will shed more light on the subject.

This tutorial is lengthy, so I will start with an overview of the steps:
  1. Create a Facebook app.
  2. Download and copy Facebook Connect into your source code.
  3. Create an FBSession with your API key and secret key.
  4. Login to Facebook via a FBLoginButton or FBLoginDialog.
  5. Enable auto re-login.
  6. Create delegate(s) that conform to the FBSessionDelegate and FBRequestDelegate protocols.
  7. Request the permissions you need.
  8. Perform actions with FBRequest.
One of the first steps to take in implementing Facebook Connect is creating a Facebook app on Facebook itself. To do this, you must add the Facebook Developer app to your profile. Finding the app is near impossible. I found it through a link on the developers page. The URL to the app is http://www.facebook.com/developers/. From there a Facebook version of your app can be created. Even though you are creating an “app,” you won’t be using it as an app. Instead, this will be the channel through which your iPhone app will interact with Facebook. This also provides some basic analytic information and creates a Facebook page for your app. I won’t go into any of the details of how to set everything up. That could be a lengthy topic by itself. Personally, I found the basics to be straightforward enough. There are many advanced capabilities that can be explored if you so desire.

With your Facebook app in place, you can now start adding the functionality to your iPhone app. You will need the Facebook Connect Xcode project. You can Google it or find it here. I found it easiest to copy the Facebook Connect project code into your own project. The greatest part of Facebook Connect is that almost everything is done for you.

Once the code is copied into your project, just #import “FBConnect.h”. Next, create a FBSession object. You should retain this object for the lifetime of your application. This is where you will need your previously created Facebook app. On the application settings editor page there is an API key and app secret key. These are necessary for creating your session object. They can be stored as string constants and passed in as parameters. the following gives an example of this.
session = [[FBSession sessionForApplication:FBAPIKey secret:FBSecretKey delegate:self] retain];

Next, to login to Facebook. This can be two different ways. The easiest is to create a FBDialogButton and add it wherever you please. If my memory serves me well, there are three different sizes of buttons that can be used. Alternately, you can create a FBLoginDialog and call that however you like. This can be done as follows:
FBLoginDialog * dialog = [[[FBLoginDialog] alloc] initWithSession:session] autorelease];
[dialog show];
Either way, a nice login dialog pops up and takes care of everything.

Facebook Connect handles automatic re-login. All you need to do is call [session resume]; when your app starts. If a user has never logged in or explicitly logged out, then this will do nothing. Also, sessions automatically expire if they are left idle for two hours.

I failed to mention earlier that you will need an object that conforms to the FBSessionDelegate protocol in order to create a session. It has a single required method:
- (void)session:(FBSession *)session didLogin:(FBUID)uid;
You can use this method as an opportunity to set a flag in your app that the user has logged into Facebook. This is also a great opportunity to request any permissions you will need later.

While on the topic of permissions, I will expound some more. FBPermissionDialog is used to request different permissions. This has two delegate methods as defined in FBRequestDelegate.
- (void)dialogDidSucceed:(FBDialog *)dialog;
- (void)dialogDidCancel:(FBDialog *)dialog;
It should be clear which does what and when it is called. The following is an example of requesting permission to publish to a user’s stream:
if (!FBPermissionsGranted) {
        FBPermissionDialog * dialog = [[[FBPermissionDialog alloc] init] autorelease];
        dialog.delegate = self;
        dialog.permission = @"publish_stream";
        [dialog show];
}

There are several different permissions that can be requested. Consult the Facebook documentation for the specifics. The only change that needs to be made to the following code is the string representing the desired permission.

One important note, Facebook remembers if a permission was previously granted. So if you request the permission a second time, the dialog window pops up and immediately closes. This quick flash is annoying and should be avoided. This can be done by saving the state of permissions granted and/or making an API call that requests the user’s granted permissions.

Now that you’ve got a user to login and granted the necessary permissions, let’s have your app do something. This is done through FBRequest. A request will look something like this:
[[FBRequest requestWithDelegate:self] call:@“some action here...” params:params];
The string is the API call to use. For example, to publish to a user’s stream call @“facebook.stream.publish” or update a user’s status with @“facebook.Users.setStatus”. The params is an NSDictionary that contains the parameters specific to that API call. Consult the Facebook API for the details. Some parameters are optional whereas others are required. If we were to publish something to the user’s stream we could set up the parameter like this:
NSDictionary *params = [NSDictionary dictionaryWithObject:@“Hello World!” forKey:@"message"];

FBRequests are where the action of Facebook Connect comes in. With the proper permissions you can do anything with a FBRequest. For example, you can upload videos, check if a user is a fan of a particular page, create events, etc. Basically, anything you can do on the Facebook website, you can do from the API. Just call the desired method, such as “video.upload,” “page.isFan,” or “events.create,” then pass in the necessary parameters. Facebook even has their own query language (FQL). This is comparable to SQL. Another point to note is that Facebook also provides a test console with each API call to test if a call works and what exactly it is returning.

I hope this lengthy tutorial is beneficial. I provided only simple examples, but really your imagination is the limit. Most of the process is very implement. The challenge comes in when making requests. Getting the parameters and return values right can take some trial and error. Making use of the Facebook test console makes life much easier.

Monday, May 10, 2010

UITableViewCell Reuse Cautions

Here’s a problem that perplexed me for quite some time today. I was making an options page for an iPhone app. I set up a UITableView with a few different sections. Each section contained different kinds of options such as dates, times, and switches. Due to the variations in options, some cells were set up differently from others. For the switches, I added a UISwitch as a subview to the content view of a cell. For dates and times, I was displaying the date or time as a detailed text label. Everything looked nice, that is until I scrolled. When scrolling, the cells had a mix of UISwitches and text labels mixed together. It was a mess. After several hours of reading documentation I uncovered the source of the problem. Ironically, it was something small and simple. When a cell scrolls off the screen it is reused as one of the cells scrolling onto the screen. Normally there are no problems with cell reuse because the cells of a table are usually uniform in use and layout. When a cell is recycled, all of the old values are usually overwritten by the new values. In my case, I wasn’t using all of the properties for all of the cells. This lead to the conflicts that left me bewildered for so long.

Removing the detailed text label was easy. All I need to do was set the it to an empty string. Removing the UISwitch wasn’t as easy. Fortunately, I found a piece of code on stackoverflow.com that helped me out. What I did was get all of the subviews from the cell’s content view and release them. It looks like this:

NSArray * subviews = [[NSArray alloc] initWithArray: cell.contentView.subviews];
        
for (UIView * subview in subviews)
        [subview removeFromSuperview];
        
[subviews release];

It was a small change but made all the difference. With those changes in place, my options page was flawless. I never cease to be amazed by all the bugs that result from simple mistakes.