Category Archives: iPhone Programming

Application Lifecycle




















User touches icon on home screen
System calls main()
main() calls UIApplicationMain()
UIApplicationMain() creates instance of UIApplication
UIApplication instance loads main Nib file, sets up based on application properties
UIApplication instance goes into run loop, waiting for and forwarding events to interface elements (instances of UIResponder)
User taps home button or does another termination activity
UIApplication instance tells your delegate that the application is terminating
UIApplicationMain() exits, main() exits, process exits

View-based Application

main.m
-Basically just the C entry point function int main(int argc, char *argv[])
-Creates an autorelease pool
-Calls UIApplicationMain which creates a UIApplication object and starts the run loop

MainWindow.xib
-Contains a UIWindow (top of the view hierarchy) for things to be installed in
-Can be (usually is) customizable per platform
-Contains the Appliation Delegate (just an NSObject which its class set to YourAppDelegate)
-Application Delegate also has a couple of outlets wired up (notably to YourAppViewController)

YourApp-Info.plist
-A variety of application configuration properties

YourAppViewController.m & .h & .xib
-Has an instance variable for the UIWindow in MainWindow.xib called window
-Has an instance variable for YourAppViewController called viewController
-Has stubs for a lot of applicationDidxxx and applicationWillxxxx
-Most importantly application:didFinishLaunchingWithOptions:
     This is the method where YourAppViewController’s view is added to the UIWindow
     Also where the UIWindow is made visible [window makeKeyAndVisible]
 

NSCopying Protocol

@protocol NSCopying
– (id) copyWithZone: (NSZone *) zone;
@end

If you adopt NSCopying, your object knows how to make copies of itself:
@interface Vehicle: NSObject<NSCopying>
{
NSColor* color;
}
// methods…
@end


-(id) copyWithZone: (NSZone *)zone {
     Vehicle * vehicleCopy = [[[self class] allocWithZone: zone] initWithColor: color];
     return vehicleCopy;
}

@interface Car: Vehicle // Car includes the <NSCopying> protocol
{
    float drivingForce;
}
// methods…
@end


// Need to implement copyWithZone, though.
// Make sure Car’s drivingForce instance variable is copied.
-(id) copyWithZone: (NSZone *)zone {
     Car * vehicleCopy = [super copyWithZone: zone];
     [vehicleCopy setDrivingForce: drivingForce];
     return vehicleCopy;
}


http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/
Protocols/NSCopying_Protocol/Reference/Reference.html



Convenience constructor

//laborious
NSNumber* zero_a = [[NSNumber alloc] initWithFloat:0.0f];

[zero_a release];

//handier
NSNumber* zero_b = [NSNumber numberWithFloat:0.0f];

//no need of release



//The Vehicle class
@interface Vehicle : NSObject
{
NSColor* color;
}
-(void) setColor:(NSColor*)color;
+(id) vehicleWithColor:(NSColor*)color;     //convenience constructor
@end





//bad convenience constructor
+(Vehicle*) vehicleWithColor:(NSColor*)color
{
//the value of “self” should not change here
self = [[self alloc] init]; // ERROR !
[self setColor:color];
return [self autorelease];
}


//Almost perfect constructor
+(id) vehicleWithColor:(NSColor*)color
{
id newInstance = [[Vehicle alloc] init]; // OK, but ignores potential sub-classes
[newInstance setColor:color];
return [newInstance autorelease];
}

@implementation Vehicle
+(id) vehicleWithColor:(NSColor*)color
{
id newInstance = [[[self class] alloc] init]; // PERFECT, the class is
                                                                              // dynamically identified
[newInstance setColor:color];
return [newInstance autorelease];
}
@end


@interface Car : Vehicle {…}
@end

//produces a (red) car
id car = [Car vehicleWithColor:[NSColor redColor]];

Autorelease

In C++


Point2D& Point2D::operator+(const Point2D & other)
{
     Point2D result(0.0f, 0.0f);
     result.v[0] = v[0] + other.v[0];
     result.v[1] = v[1] + other.v[1];
     return result;
} //ERROR – it results in a dangling reference because the local object is destructed prior to the return of the function



Point2D& Point2D::operator+(const Point2D & other)
{
     Point2D * result = new Point2D();
     result.v[0] = v[0] + other.v[0];
     result.v[1] = v[1] + other.v[1];
     return result;
} //ERROR – it results in memory leakage because nobody will delete the created object



Point2D Point2D::operator+ (const Point2D &other)
{
     Point2D result(0.0f, 0.0f);
     result.v[0] = v[0] + other.v[0];
     result.v[1] = v[1] + other.v[1];
     return result;
} // CORRECT – it returns a local class object by value
Point2D&
Point2D::operator+= (const Point2D &other)
{
     v[0] += other.v[0];
     v[1] += other.v[1];
     return *this;
} // CORRECT – it returns a self by reference




In Objective-C


-(Point2D*) add:(Point2D*)p1 and:(Point2D*)p2
{
     Point2D* result = [[Point2D alloc] initWithX:([p1 getX] + [p2 getX])
                                             andY:([p1 getY] + [p2 getY])];
     return result;
}
//ERROR : the function performs “alloc”, so, it is creating
//an object with a reference counter of 1. According
//to the rule, it should destroy the object.
//This can lead to a memory leak when summing three points :
[calculator add:[calculator add:p1 and:p2] and:p3];
//The result of the first addition is anonymous
//and nobody can release it. It is a memory leak.


-(Point2D*) add:(Point2D*)p1 and:(Point2D*)p2
{
     return [[Point2D alloc] initWithX:([p1 getX] + [p2 getX])
                                  andY:([p1 getY] + [p2 getY])];
}
//ERROR : This is exactly the same code as above. The fact that
//no intermediate variable is used does not change anything.


-(Point2D*) add:(Point2D*)p1 and:(Point2D*)p2
{
     Point2D* result = [[Point2D alloc] initWithX:([p1 getX] + [p2 getX])
                                             andY:([p1 getY] + [p2 getY])];
     [result release];
     return result;
}
//ERROR : obviously, it is nonsense to destroy the object after creating it



-(Point2D*) add:(Point2D*)p1 and:(Point2D*)p2
{
     Point2D* result = [[Point2D alloc] initWithX:([p1 getX] + [p2 getX])
                                             andY:([p1 getY] + [p2 getY])];
     [result autorelease];
     return result; //a shorter writing is “return [result autorelease]”
}
//CORRECT : “result” will be automatically released later,
//after being used in the calling code