Tuesday, April 13, 2010

Objective-C Tuesdays: instance variables

Last time we talked about local variables and function parameters. Today we will look at instance variables of Objective-C classes and we'll touch on methods as well.

Objective-C classes are defined by an @interface section and an @implementation section. The @interface section declares the instance variables and looks like this:
@interface Cat : NSObject {
  NSString *name;
  int age;
}

- (id)initWithName:(NSString *)aName
            andAge:(int)anAge;

// ...
@end
The instance variables (or ivars) are declared between the curly braces, after the class name and superclass but before method declarations. Instance variables are declared like any local or global variable, but have a different scope. By default, instance variables are visible in all instance methods of a class and its subclasses. (Instance methods are the ones that begin with a minus sign.) The implementation of the -init method might look like this:
// example of using instance variables
@implementation Cat

- (id)initWithName:(NSString *)aName
            andAge:(int)anAge
{
  self = [super init];
  if ( ! self) return nil;
  
  name = [aName copy];
  age = anAge;
  
  return self;
}

// ...
@end
This is a pretty standard Objective-C -init method. Note that unlike JavaScript, Python, Ruby and many other languages, there's no need to prefix instance variables with this, self, @ or something similar. But this leads to a problem: what if a method parameter has the same name as an instance variable? If our -init method was defined like this:
// example of name shadowing
- (id)initWithName:(NSString *)name
            andAge:(int)age
{
  self = [super init];
  if ( ! self) return nil;
  
  name = [name copy]; // causes a warning
  age = age;          // causes a warning
  
  return self;
}
If you compile this code, you'll see warnings like local declaration of 'name' hides instance variable. You should heed these warnings! Code like
age = age;
assigns parameter age to itself, leaving the instance variable age unchanged.

Unfortunately there's no elegant way to deal with parameters shadowing instance variables. Objective-C does allow you to use the "pointer to member" or "arrow" (->) operator on self to access instance variables, like this:
// example of pointer to member
- (id)initWithName:(NSString *)name
            andAge:(int)age
{
  self = [super init];
  if ( ! self) return nil;
  
  self->name = [name copy]; // still causes a warning
  self->age = age;          // still causes a warning
  
  return self;
}
If you know C++ or Java, you would think this would work, but the Objective-C compiler still produces a warning. This is probably one of the most niggling little differences between Objective-C and other languages that you just need to get over. The only practical solution is make sure that parameter names don't clash with instance variables. For initializers and setters, most Objective-C programmers simply prefix their parameter names with "a", "an" or "the". It's not very elegant, but it works. If you're tempted to simply prefix your instance variable names with an underscore, I recommend against that. Apple uses the leading underscore convention in framework classes in order to prevent name clashes when application writers have to extend framework classes.

The struct behind the curtain
If you're familiar with C or C++, seeing an expression like self->name should give you a clue to the inner workings of Objective-C. Underneath, Objective-C objects are pretty much just structs and functions. The @interface of our Cat class:
@interface Cat : NSObject {
  NSString *name;
  int age;
}
// ...
@end
becomes a struct that looks something like:
// pseudocode for struct generated for Cat class
struct Cat {
  Class isa;       // inherited from NSObject
  NSString *name;
  int age;
};
The instance variables you define are tacked on to those defined by the superclass, and its superclass and so on. So if we defined a subclass of Cat:
@interface LolCat : Cat {
  UIImage *picture;
  NSString *caption;
  int upVotes;
}
@end
the Objective-C compiler would generate a structure in memory that looked something like:
// pseudocode for struct generated for LolCat class
struct LolCat {
  Class isa;         // inherited from NSObject
  NSString *name;    // inherited from Cat
  int age;           // inherited from Cat
  UIImage *picture;
  NSString *caption;
  int upVotes;
};
Similarly, Objective-C methods are simply regular C functions underneath with extra parameters automatically added by the compiler. So our -init method
- (id)initWithName:(NSString *)aName
            andAge:(int)anAge
{
  // ...
}
is compiled into something that resembles:
// pseudocode for function generated for -initWithName:andAge: method
id initWithName_andAge(id self, SEL _cmd, NSString *aName, int anAge) {
  // ...
}
The parameters self and _cmd are added to each instance method by the compiler. Naturally, self is a pointer to the memory for the instance, organized like a struct as we've shown. The _cmd parameter holds the method selector (which is basically the method name) and can be used to do very crazy dynamic stuff we won't dive into today.

Instance variable scope
We mentioned earlier that by default, instance variables are visible in all instance methods of a class and its subclasses. This is referred to as protected scope in Objective-C. You can change the scope of instance variables to be private, public or package as well as protected, but in general these other scopes aren't used very frequently in Objective-C. Going back to our Cat example, you would use the scope specifiers like this:
@interface Cat : NSObject {
  // protected by default
    double weight;
  @private
    int lives;
  @protected
    int age;
  @public
    NSString *name;
  @package
    UIColor *color;
}

// ...
@end
Private scope restricts visibility of the instance variable to the class it's defined in; subclasses are not allowed to use it. Protected is the default if you don't specify a scope, and allows all subclasses to read and write to the instance variable. Public scope is rarely seen in Objective-C; the pointer to member or arrow (->) operator is used to access public instance variables:
// accessing public instance variables
Cat *cat = [[Cat alloc] init];
NSLog(@"The cat's name is %@", cat->name);
Package scope is used by framework creators; it makes the instance variable public within the framework and private outside it.

Properties
Since instance variables aren't visible outside classes by default, most Objective-C programmers create getters and setters when they want to expose instance variables. Before Objective-C 2.0, these were written by hand for each instance variable:
// getter and setter declarations
@interface Cat : NSObject {
  NSString *name;
  int age;
}

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

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

// ...
@end
The normal Objective-C convention is to give the getter the same name as the instance variable and to prefix the setter with "set". The implementation of simple setters is boilerplate but not trivial due to the need to manage retain counts:
// getter and setter definitions
@implementation Cat

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

// ...
@end
Writing setters manually is both laborious and error prone, so Objective-C 2.0 introduced properties, allowing getters and setters to be generated automatically. Rewriting the Cat class using properties:
// property declaration
@interface Cat : NSObject {
  NSString *name;
  int age;
}

@property(copy, nonatomic) NSString *name;
@property(assign, nonatomic) int age;

// ...
@end
And its implementation:
// property implementation
@implementation Cat

@synthesize name, age;

// ...
@end
Which is much better. Properties can be called in two ways. Dot notation is the most terse and similar to many other languages:
// property dot notation example
Cat *cat = [[Cat alloc] init];
NSLog(@"The cat is %d years old", cat.age);
cat.name = @"Ritz";
But you can use normal method calls as well:
// property method call example
Cat *cat = [[Cat alloc] init];
NSLog(@"The cat is %d years old", [cat age]);
[cat setName:@"Ritz"];
These two examples are exactly equivalent. Dot notation is simply syntactic sugar for getter and setter method calls.

Which is which?
While it's very convenient, property dot notation makes Objective-C a little confusing at first. You will sometimes see properties and instance variables mixed together in the same method:
- (void)celebrateBirthday {
  age++; // instance variable
  if (age > 9) {
    self.name = // property
            [NSString stringWithFormat:@"Old %@", 
                                name]; // instance variable
  }
}
At first glance, name and self.name don't seem that different but they are. We'll examine those differences, and look more at properties, next time.

Friday, April 9, 2010

iPad Friday: April 9, 2010

Hello all you lucky owners of a magical and revolutionary new mobile device (and you know who you are).  Here are a set of iPad wallpapers from today's iPhone Friday scaled to fit your beautiful display.  Enjoy!

(Click the image for the full-size image)






iPhone Friday - April 9, 2010

Hello and happy Friday to you all.  Today's iPhone and iPod touch wallpapers come from a response to the iPad wallpapers from last week (thank you Carmen).  They are some pictures I took the garden yesterday.  I have cropped them down for iPhone/iPod touch and will also post a follow-up entry for the iPad as well.  Cheers!






Tuesday, April 6, 2010

Objective-C Tuesdays: local variables and function parameters

Last time when we looked at static variables declared inside functions, we touched on local variables. Today we'll focus on local variables and function parameters.

Local variables in C and Objective-C are declared like this:
// local variable examples
void myFunction() {
  // declare some local variables ...
  int i; // uninitialized, will have some random value
  NSString *s = @"foobar";
  double sqrtOf2 = sqrt(2);
  
  // do stuff ...
}
Local variables are not initialized to zero, NULL or nil by default the way global variables are. It's important to initialize a local variable before you use it, otherwise its initial value will be something random and almost certainly not something useful. Function parameters are very similar to local variables, except that their value is defined by the caller of the function.
// function parameter examples
void yourFunction(int i, NSString *s, double d) {
  // do stuff ...
}
In very old C code, you may sometimes see function parameters declared like this:
// old function parameter style
myOldFunction(i, s, d) // only parameter names go here
  int i;
  NSString *s;
  double d;
  // parameter types are defined between
  // the parameter list and curly brace
{
  // do stuff ...
}
This old style is called K&R C (for Kernighan & Ritchie, the authors of The C Programming Language book) and has been replaced by the modern ANSI C style you're used to, but you many occasionally see it in very old code or examples. (In fact, the function return type is optional in K&R C and defaults to int if not given.)

Function parameters are available for the complete time that the function is executing. Local variables however can have a more limited lifespan. Typically, local variables are local to a function body, but they can also be local to the body of an if, for, while and do-while statement:
void printSquares() {
  int x;
  
  for (x = 0; x < 10; ++x) {
    int x_squared = x * x; // only valid in the for loop

    printf("%i^2 = %i\n", x, x_squared);
  }
  // x_squared no longer valid
  // x still valid
}
In fact, you can even use a set of curly braces alone to create a new local variable scope:
void someFunction() {
  int x;
  
  // new local scope
  {
    int foo = 10; // local variable foo now valid
    // ... do something with foo
  }

  // foo no longer valid
  // x still valid
}
In older versions of C and Objective-C, all local variables had to be declared at the start of a function or statement block. So something like this:
void someFunction() {
  int x = 10;
  printf("x = %d\n", x);
  
  int y = 20; // not allowed before C99
  printf("y = %d\n", y);
}
would not compile. The C99 standard changed this to allow local variables to be declared at any point in a function, something that C++ has always allowed. By default, Xcode Objective-C projects compile using C99 rules (this is set by the C Language Dialect build setting in Xcode or the -std=c99 command line parameter to gcc).

Next time, we will look at instance variables of Objective-C classes.

Monday, April 5, 2010

Tired of iPad hype? Get excited about iPhone OS 4!

Did you spend the weekend playing with your iPad? (I did :-) Or are you waiting impatiently for the iPad 3G models to arrive later this month? Tired of all the hype already? Well Apple's not giving you a break yet. Gizmodo is reporting this morning that invitations have gone out for a "sneak peak into the future of iPhone OS." The event is this Thursday, 8 April at 10 AM Pacific time.

Anyone want to guess what new features are in store? Multitasking? iPhone versions of Pages and Numbers? New phone hardware?  iPhone on Verizon's network?  A front-facing camera for video chat? All I know is that Apple will surely surprise and delight.

Saturday, April 3, 2010

iPad Wallpaper: April 3, 2010

Hello, new friend.  I will hug you and pet you and name you George.  (That's short for "gorgeous" which is exactly what Apple's iPad is.)  Today Apple is releasing their latest mobile device which both Don and I, along with friends, will be picking up today.  Woot!

In honor of this event I am providing you (the fortunate ones to pick up an iPad) with eight iPad wallpaper images at a beautiful 1024 x 767 pixel resolution.  I have created more but I think eight will be a good start, and you may like one of them.

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







Friday, April 2, 2010

iPhone Friday - April 2, 2010

Happy Friday.  Today's iPhone wallpapers are all about Spring...  Japanese style.