Tuesday, April 27, 2010

Objective-C Tuesdays: @property and @synthesize

Last time we looked at writing getters and setters for Objective-C classes. Today we'll look at generating them automatically using the @property and @synthesize directives.

Before Objective-C 2.0 was introduced, if you wanted to add getters and setters to a class, you wrote them yourself using instance methods, which caused some classes to become heavy with boilerplate code:
// example of hand-written getters and setters
@interface Person : NSObject {
  int age;
  Address *address;
  NSString *name;
}

- (int)age;
- (void)setAge:(int)anAge;

- (Address *)address;
- (void)setAddress:(Address *)anAddress;

- (NSString *)name;
- (void)setName:(NSString *)aName;

// ...

@end


@implementation Person

- (int)age {
  return age;
}

// assign-type setter
- (void)setAge:(int)anAge {
  age = anAge;
}

- (Address *)address {
  return address;
}

// retain-type setter
- (void)setAddress:(Address *)anAddress {
  if (address != anAddress) {
    [address release];
    address = [anAddress retain];
  }
}

- (NSString *)name {
  return name;
}

// copy-type setter
- (void)setName:(NSString *)aName {
  if (name != aName) {
    [name release];
    name = [aName copy];
  }
}

// ...

@end
This is a lot of code to write, and the Person class barely does anything yet. The @property directive will remove some of the boilerplate code from the @interface section of the class and the @synthesize directive will clean up the @implementation

Declaring properties
A getter and setter form a logical property of a class. Properties typically correspond directly to instance variables, but don't have to. Sometimes a property is calculated on the fly, or the name of the instance variable is different than the name of the property. The @property directive replaces the getter and setter method declarations in the @interface of the class.
// declaring age property
@interface Person : NSObject {
  int age;
  Address *address;
  NSString *name;
}

@property int age;

// ...
@end
Notice that the property declaration looks a lot like an instance variable declaration. At a high level, a property is very similar to an instance variable. But as far as the compiler cares, a @property is simply a replacement for declaring the getter and setter methods:
@property int age;
is just a substitute for
- (int)age;
- (void)setAge:(int)anAge;
If you don't write the corresponding getter and setter methods in the @implementation section, you'll see compiler warnings like this:
property 'age' requires method '-age' to be defined - use @synthesize, @dynamic or provide a method implementation
property 'age' requires the method 'setAge:' to be defined - use @synthesize, @dynamic or provide a method implementation

Read-only properties
Sometimes, you want properties to be read-only. For example, we might store the person's birthdate instead of age:
// age property calculated on the fly
@interface Person : NSObject {
  NSDate *birthDate;
  Address *address;
  NSString *name;
}

@property int age;

// ...
@end

@implementation Person

- (int)age {
  NSCalendar *calendar = [NSCalendar currentCalendar];
  NSDate *today = [NSDate date];
  NSDateComponents *components = [calendar components:NSYearCalendarUnit 
                                             fromDate:birthDate 
                                               toDate:today 
                                              options:0];
  return components.year;
}

// ...
@end
Yet it doesn't make sense to write the corresponding setAge: method here. If we compile this code, we'll still get nagged about the setter:
property 'age' requires the method 'setAge:' to be defined - use @synthesize, @dynamic or provide a method implementation
To silence this, we need to add an attribute to the property. Property attributes go in parentheses after the @property keyword but before the type and name:
@property (readonly) int age;
Here we've told the compiler that the age property is readonly, so not to worry about the setter. By default, properties are readwrite. You can label them with the readwrite attribute, but since it's the default, it's redundant and you'll rarely see it.

Object properties
Let's set aside the calculated age property and go with our plain old int version. The next property of the Person class is address:
// declaring address property
@interface Person : NSObject {
  int age;
  Address *address;
  NSString *name;
}

@property int age;
@property Address *address;

// ...
@end
When you compile this, you'll see warnings like:
no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed
assign attribute (default) not appropriate for non-gc object property 'address'
The compiler has noticed that address is an Objective-C object type and is reminding you to do the appropriate memory management. (Those lucky Mac developers don't have to worry about this any more since they now have garbage collection.) In addition to readwrite/readonly there's another set of property attributes: assign, retain and copy. Since address uses retain memory management, we'll change it to look like
@property (retain) Address *address;
At this stage, assign, retain and copy are simply documentation to other programmers about the memory management strategy for the property. If you write the setter yourself, the compiler isn't smart enough to tell if you actually wrote the correct type of setter, so be careful! There's nothing worse than code that says it's doing one thing and actually does another. So what's the point? We'll see when we get to @synthesize.

Finishing up the properties for our class, we declare a property for name that uses a copy memory management scheme. (Last week's post explained why we use copy for NSString properties.)
// declaring name property
@interface Person : NSObject {
  int age;
  Address *address;
  NSString *name;
}

@property int age;
@property (retain) Address *address;
@property (copy) NSString *name;

// ...
@end

Plain old pointer properties
Most Objective-C code uses objects instead of plain old C structs, strings and arrays, but sometimes you'll need to use them, often when working with low level C libraries. You might be tempted to document your memory management for these plain old pointers as you would Objective-C objects:
// ERROR: won't compile
@interface Person : NSObject {
  int age;
  Address *address;
  NSString *name;
  char const *username; // plain old C string
}

@property int age;
@property (retain) Address *address;
@property (copy) NSString *name;
@property (copy) char const *username; // plain old C string

// ...
@end
Unfortunately, since plain old C types don't have retain/release memory management like Objective-C objects, this muddies the meaning of copy and the compiler will stop with an error like:
property 'username' with 'copy' attribute must be of object type
Unfortunately, marking a property like this assign when your setter actually makes a copy doesn't seem right either:
// not quite right
@property (assign) char const *username;
My advice is to leave off assign, retain and copy from properties for plain old C pointers and use a comment to note your memory management strategy.

I'm out of time right now, so I'll have to finish this up next week. Coming up, the nonatomic property attribute, and the @synthesize directive.

Friday, April 23, 2010

iPad Friday: April 23, 2010

Hello and happy Friday to you all.  Today we are continuing with the Images of Spring collection iPad wallpapers.  The full-size iPad wallpapers are 1024 x 1024 so that you'll have the best resolution in both portrait and landscape orientations.  Enjoy.

(click on image for full-size wallpaper)





iPhone Friday: April 23, 2010

Hello and happy Friday to you all.  Today we are continuing with the Images of Spring collection of iPhone wallpapers.  Enjoy.

(click on image for full-size wallpaper)








Wednesday, April 21, 2010

Android 2010 is Windows 1990

In an article titled Three Android lessons learned the hard way, Jonathan Blum talks about his experiences deploying Android phones in his business. It's a typical journal of a user working with a nascent technology, something we've all seen and done before in various incarnations. But one passage struck me as all too familiar:
Plan on carefully testing apps on your businesses phones before unleashing them on your entire operation. Trust me, nothing is more frustrating than not being able to answer a client's call because ESPN Mobile is installed.
If you've ever worked in any large enterprise with a full time IT staff, you're familiar with IT testing new versions of Windows before rolling out a company-wide upgrade, or qualifying a new application before deploying it to users' computers. In most big companies, there's no "personal" in PC anymore.

Is this where Android is headed? Are we going to have sysadmins for our business phones? Is IT going to lock them down to keep us monkeys from installing too many apps? Really?

Tuesday, April 20, 2010

Objective-C Tuesdays: instance variables, getters and setters

Last time we looked at instance variables of Objective-C classes. Today we're going to look at writing getters and setters for instance variables.

As we saw, instance variables have protected scope by default, which makes them visible in instance methods of the class that defines them and all subclasses, but hidden to all other code and classes by default. Hiding the inner workings of a class is a principal of object oriented programming known as encapsulation. In general, it's better to tell your objects what to do rather than ask them for their data. But there are times when you need to get and set an object's data directly, particularly for objects that correspond to those things your application and users directly manipulate, like address book contacts or cookie recipes. The typical way to do this is to write getter and setter methods. Before Objective-C 2.0, these were always written by hand, and there are still times when you would want to write your own rather have the compiler generate them for you using the @property and @synthesize directives.

Getters
A conventional getter method in Objective-C has the same name as the instance variable:
// getter method example
@interface CookieRecipe : NSObject {
  NSString *name;  // instance variable name
}
- (NSString *)name; // getter method for name ivar
@end

@implementation CookieRecipe

- (NSString *)name { // getter method for name ivar
  return name;
}

@end
This works because instance variables and instance methods live in separate namespaces. The compiler can always figure out whether you're calling a method or accessing an instance variable, so there's never a problem. Getter methods are generally very simple and rarely have side effects.

Compiler generated getters are as simple as the example above. There are two common cases where you might want to write them by hand: calculated properties and defensive copying.

Sometimes a class has a property that's easily calculated from other properties, such as a fullName property that can be created on the fly by joining firstName and lastName, or a yearsWithCompany property that's calculated by subtracting hireDate from today's date. These types of properties are usually read only and quick to calculate.

Defensive copying is done when your object has some mutable internal data that it needs to share with other code, but which other code should not change. For example, you might have a User class that has an NSMutableArray containing the user's friends:
// example of exposing mutable internals
@interface User : NSObject {
  NSMutableArray *friends; // contains other Users
}
- (NSMutableArray *)friends;
@end

@implementation User

- (NSMutableArray *)friends {
  return friends;
}

@end
The friends getter returns the friends instance variable directly. This might work out okay if all the code that uses friends is polite and only reads the list of friends. But it's all to easy to innocently do something like this:
// accidentally changing internal state

NSMutableArray *boneheads = [user friends]; 
// boneheads now points to same mutable array that 
// the friends instance variable does

NSPredicate *boneheadsOnly = [NSPredicate predicateWithFormat:@"species == 'Minbari'"];
[boneheads filterUsingPredicate: boneheadsOnly]; 
// oops! all the user's non-Minbari friends are gone
// -filterUsingPredicate: removes items that don't match
Mutable objects like NSMutableArray naturally have methods like -filterUsingPredicate: that change the data they contain. By sharing a mutable instance variable directly, the User class allows other code to intentionally or unintentionally muck around with its internal state, breaking encapsulation. While bugs caused by unintentional mucking aren't usually too hard to track down, it's the intentional mucking that causes more trouble in the long run. By exposing its internals like this, the User class allows itself to become closely coupled with the code that calls it, since callers can add or remove items directly to or from the friends collection. The rules for adding and removing friends get spread around the app in numerous locations rather than centralized in User, making the system harder to understand, harder to change; small changes in User then affect more of the code than necessary.

So rather than return a mutable internal value directly, there are a couple of options in Objective-C. When you're using a class like NSMutableArray that has an immutable superclass, you can upcast the returned instance variable to the immutable superclass:
// getter that upcasts to immutable superclass
@interface User : NSObject {
  NSMutableArray *friends; // instance variable is mutable
}
- (NSArray *)friends;
@end

@implementation User

// return type of getter is immutable
- (NSArray *)friends {
  return friends;
}

@end
It's called upcasting since it casts a subclass reference "up" to a superclass reference. Because this is always a safe cast, Objective-C will do this automatically for you with no explicit cast is needed. While this won't prevent a malicious programmer from downcasting the result back to its mutable type and mucking around, in practice this works pretty well (and if you have a malicious programmer on your team, you have a bigger problem than a little code can solve).

Sometimes the instance variable you want to share doesn't have an immutable superclass, or most callers of the getter need to filter or manipulate the returned value. In that case, you can do an actual defensive copy:
// getter that does a defensive copy
@interface User : NSObject {
  NSMutableArray *friends; // instance variable is mutable
}
- (NSMutableArray *)friends;
@end

@implementation User

// return type of getter is mutable
- (NSMutableArray *)friends {
  // return an autoreleased copy
  return [[friends mutableCopy] autorelease];
}

@end
Now the caller can delete your friends all they want. You can use whichever creation or copy method is appropriate for the mutable data; just make sure to properly autorelease the return value.

Setters
The Objective-C convention for setter names is similar to Java's: capitalize the instance variable name and prefix with set. Setters come in different varieties, depending on the type of instance variable. The simplest kind is used for primitive types like ints and object references that aren't retained, like delegates.
// assignment setter
- (void)setAge:(int)anAge {
  age = anAge;
}
Assignment setters are trivial, but the fun starts when you have to deal with memory management and retain counts. Here's an example of a setter that retains the new value and releases the old one, but it has a subtle bug:
// retain setter WITH BUG
- (void)setAddress:(Address *)theAddress {
  [address release];             // release old address
  address = [theAddress retain]; // retain new address
}
This setter might never give you a problem, if you're lucky. But what happens if the new address and old address are the same object? What happens when that object's retain count is 1?
// retain setter WITH BUG
// suppose address == theAddress
// and retain count is 1
- (void)setAddress:(Address *)theAddress { 
                                 // retain count is 1
  [address release];             // retain count now 0, 
                                 //     dealloc called
  address = [theAddress retain]; // oops! theAddress points at  
                                 //     invalid memory
}
There are two common ways to write a setter to get around this. The first way is to check for self-assignment:
// retain setter with self-assignment check
- (void)setAddress:(Address *)theAddress {
  if (theAddress != address) {
    [address release];             // release old address
    address = [theAddress retain]; // retain new address
  }
}
The second way is to retain first and release last:
// retain setter that retains first
- (void)setAddress:(Address *)theAddress {
  [theAddress retain];  // retain new address
  [address release];    // release old address
  address = theAddress;
}
This will prevent the retain count from going to zero in the case of self-assignment.

Just as you may want to defensively copy in a getter, you may want to do the same in a setter. Here's an example a malicious programmer would love:
// be careful with that setter
@interface User : NSObject {
  NSString *name;
}
- (void)setName:(NSString *)aName;
@end

@implementation User

- (void)setName:(NSString *)aName {
  if (aName != name) {
    [name release];
    name = [aName retain];
  }
}

@end
Looks normal, right? But what if I do this:
// don't change that mutable object!
NSMutableString *someName = [@"Joe User" mutableCopy];

User user = // ...
[user setName: someName];
// okay cool, user's name is now "Joe User"

[someName appendString:@" Doodoo Head"];
// oops, user's name and someName point to the same object
// which now contains "Joe User Doodoo Head"
So even though you thought you were using an immutable NSString for your user's name, many common Cocoa Touch classes like NSString and NSArray have mutable subclasses, and your object's callers can accidentally give you a mutable instance that they modify later. So when you're writing setters in this situation, you should defensively copy the value you receive.
// setter that defensively copies

- (void)setName:(NSString *)aName {
  if (aName != name) {
    [name release];
    name = [aName copy];
  }
}
You can use the -copy method if the object implements the NSCopying protocol, or any creation method that produces a new independent object. (Just make sure to retain that copy if appropriate).

Next time, we'll look at how the @property and @synthesize directives are used in modern Objective-C to generate getters and setters automatically.

Friday, April 16, 2010

iPad Friday: April 16, 2010

Hello and happy iPad Friday to all you lucky iPad owners.  Today's iPad wallpapers are a continuation of Images of Spring which we began last week.  There are the iPhone and iPod touch versions also available for those of us who do not have the magical and revolutionary new mobile device from Apple.  Enjoy!

(Click on an image to open the full-size version.)



iPhone Friday - April 16, 2010

Hello and happy Friday.  Today's collection of iPhone and iPad wallpapers continues the Images of Spring series.  And for you iPad owners, there is a iPad Fridays thread just for you.  Enjoy!

(Click on an image to open the full-size version.)