I'm thinking about developing some applications for iPhone. I've never code anything for Mac, so starting this trip to IPhone, the first stop is ObjC/Cocoa. Here I have collected some information I found useful for C++ programmer to start coding ObjC .
Concepts Translation
In ObjC compare to C++, the basic object oriented programming concepts are called in a different way. I use this easy table to make the translation.
C++ | ObjC |
Class | Object |
Member function | Method |
Data members | Instance variables |
Constructor | Initializer |
Destructor | Deallocator |
Multiple Inheritance | Not available :D |
Member function call | Object message |
Method declaration & Messages
ObjC syntax for methods is based on Smalltalk so there is nothing in common with C++. To show how to send a message to a instance let's suppose I already have an instance MyObject *objectInstance; declared.
Declaration / Message
The following table shows several examples of method declaration and method invocation = messaging
method: doSomething arguments: 0 return value: 0 | |
declaration | messaging |
-(void) doSomething; | [objectInstance doSomething]; |
method: getAnIntetger arguments: 0 return value: 1(int) | |
declaration | messaging |
-(int) getAnIntetger; | int result = [objectInstance getAnInteger]; |
method: setAnInteger arguments: 1(int) return value: 0 | |
declaration | messaging |
-(void) setAnInteger:(int)value; | [objectInstance setAnInteger:5]; |
method: setAnIntegerAndString arguments:2 (int, string) return value: 0 | |
declaration | messaging |
-(void) setAnIntegerAndString:(int)value withString:(NSString *)string; | [objectInstance setAnIntegerAndString:5 withString:@"Jurl Jurl"]; |
If you replace - with + in the declaration, then the instance method becomes a class methods
NSObject
When you use ObjC to write code based on the Foundation Framework, NSObject is the superclass that your classes should inherit from . The Foundation Framework, as its name highlights, is the main framework of the Cocoa Lib. Corollary: All your classes should inherit from NSObject.
Main methods implemented by NSObject
-(id) init | Default constructor |
(NSString *) description | Returns a string with a brief description of the object |
(BOOL) isEqual: (id)anObject | Compare object instances and returns YES if they are the same and NO otherwise |
Simple Object/Class Declaration
I prefer learning from examples. So from here I will start writing a simple object to show the fundamentals to code classes in ObjC.
FILE: MyObject.h
#import <Foundation/Foundation.h> @interface MyObject : NSObject { // Declare instance variables // Basic types allocation is managed by the compiler int m_value; // Class instances are always managed through pointers // Allocation is a coder responsability NSString *m_string; } // Declare methods - (int) getValue; - (void) setValue: (int) value; - (NSString *) getString; - (void) setString: (NSString *) string; @end
Simple Object/Class Definition
FILE: MyObject.m
#import "MyObject.h"
@implementation MyObject
// Define methods
- (int) getValue
{
// Compiler returns this value doing a copy
return m_value;
}
- (void) setValue: (int) value { // Compiler manages the copy of basic types variables m_value = value; } - (NSString *) getString { // We just return a pointer, not a copy of the class instance return m_string; } - (void) setString: (NSString *) string { if (string) { // We tell the memory manager we have just finished using m_string instance [m_string release]; // We point to the new string and tell the memory manager // that we are going to use the instance we have receive m_string = [string retain]; } }
@end
Intializers. Object instance creation
In ObjC, to create an instance of an object, you need explicitly 2 steps:
- Allocation
- Constructor/Initializer
Following code shows who create an object instance. Take a look at the ObjC message nesting syntax.
MyString *myString = [[MyString alloc] init];
Overwritting NSObject init method
To customize your object initialization is as easy as overwriting the init method of NSObject
FILE: MyObject.m (APPEND)
// id is the common type of any NSObject - (id) init { // First init the super class and check everything went OK if (![super init]) return nil; // Set initial value m_value = 75.0f; // Return instance, self = this return self; }
Custom initializer with arguments
If you want your own customized initializer, you can do it of course. Let's see how to.
FILE: MyObject.h (APPEND)
- (id) initWithString: (NSString*)string;
FILE: MyObject.m (APPEND)
- (id) init
{
return [self initWithString: [[NSString alloc] initWithFormat:@"defaultTitle"]];
}
- (id) initWithString: (NSString *)string
{
if (![super init]) return nil;
m_value = 75.0f;
// Use retain to keep the
m_string = [string retain];
return self;
}
Understanding Memory Management
The memory management in ObjC is based on reference counting. All NSObjects have a retain counter.
- MyObject *myObject = [MyObject alloc];
//returns an instance with retainCounter = - [myObject retain];
//make retainCounter++, call retain method if you want to keep the instance alive - [myObject release];
// make retainCounter--, call release method when you have finished using the instance - When the retainCounter == 0, the dealloc method is called.
First thing required to avoid memory leaks is to implement dealloc method
FILE: MyObject.m (APPEND)
-(void) dealloc { [m_string release]; [super dealloc]; }
AutoRelease
There is another way to avoid memory leaks without taking care of the retain counters. At least in iPhone applications you need to instance an allocation pool. And as far as I know, to do so, you create an NSAutoreleasePool instance during the initialization process. You can use the autorelease message to make the NSAutoreleasePool responsible for deallocating the object instances. Using this feature you do not control when the instance will be deallocated, it will depend on NSAutoreleasePool strategies.
This technique is NOT recommended for iPhone, because the memory resources of the phone aren't very large and it's a good idea deallocate instances as soon as they are not useful. But there are circumstances where there is no other option. If you want to overwrite NSObject method description, where you need to return an NSString, if you don't want to keep a description string as an instance variable you have to return an autorelease string because you can't release the return value before returning it.
- (NSString *) description
{
NSString *result;
result = [[NSString alloc] initWithFormat: @"Just an object to test];
[result autorelease];
// Alternative using class method
// result = [NSString stringWithFormat:@"Just an object to test"];
return result;
}
No comments:
Post a Comment