Objective-C Class and Method

Objective-C Class

Objective-C class interface

  • Declares instance variables and public methods
    MyString.h
    #import <Cocoa/Cocoa.h>
    
    @interface MyString : NSObject {
      // Declare instance variables
      NSString* value;
    }
    
    // Declare methods
    - (NSString*) value;
    - (void) setValue: (NSString*)input;
    
    + (NSString*) append:(NSString *)fromString target:(NSString *)toString;
    @end
  • MyString class inherits a predefined top level Objective-C class NSObject (root object)
    • NSObject is a root object for the basic framework for Objective-C
    • For best practice, application Objects should be a descendant of NSObject
      @interface MyString : NSObject {
  • dash "+" sign means this is an Objective-C class method
  • dash "-" sign means this is an Objective-C instance method
    - (NSString*) value;
  • Define an instance variable value of a pointer type to NSString
    NSString* value;
    • "*" indicates a pointer type
    • All Objective-C object variables are pointer types
    • All instance variable is private by default and require a setter and getter method to access
    • All instance variable is initialized as nil
  • Declare a getter method for value
    - (NSString*) value;
    • Contrast to other language, the getter method does not prefix with get like getValue
  • Declare a setter method
    - (void) setValue: (NSString*)input;
    • Set the value with the parameter input
  • Declare a method taking multiple parameters
    + (NSString*) append:(NSString *)fromString myTarget:(NSString *)toString;
    • Objective-C handles multiple parameters different from other languages
      • The above method actually created a method name called append:myTarget: with parameters fromString and toString, equivalent in other language
        obj.appendMyTarget(fromString, toString)
        + (NSString*) add:(NSString *)fromString value2:(NSString *)toString;

Objective-C Implementation Class

Contains the implementation code and the private method

MyString.m
#import "MyString.h"

@implementation MyString

- (NSString*) value {
    return value;
}

- (void) setValue: (NSString*)input
{
    [value autorelease];
    value = [input retain];
}

@end

Objective-C Methods

Sending a message to an Objective-C object

  • Sending a message in Objective-C equivalent to call a method in Java
    // Equivalent to myObject.myMethod(); in Java
    [myObject myMethod];
    
    // Equivalent to myObject.myMethod2(v1); in Java
    [myObject myMethod2:v1];
    
    // Equivalent to String result = myObject.method3(); in Java
    NSString* result = [myObject myMethod3];
  • myMethod3 return an pointer of type NSString
  • the object receiving the message is called a receiver

Sending a message to an Objective-C class

// Similar to NSString result = NSString.string(); in Java
NSString* result = [NSString string];
  • Sending a message to the class method string of NSString

Sending message to an Objective-C method with multiple parameters

// Similar to obj.add(v1, v2); in Java
[obj add:v1 value2:v2];
  • Objective-C combines all the first parameter in the "name:value" pair to form the method name add:value2 used by the runtimes
  • v1 and v2 are 2 parameters to the Objective-C method add:value2:
    Method Declaration
    // Similar to add(String fromString, String toString) in Java
    + (NSString*) add:(NSString *)fromString value2:(NSString *)toString;
  • parameters are order sensitive
    // Invalid
    [obj value2:v1 add:v2];
  • parameters, if declared, cannot be optional (or with default value) like PHP or Ruby
    // Invalid
    [obj value2:];

Methods with variable parameters

[obj myMethod:v1, v2, v3, v4];

Sending message within another message

[obj myMethod1:[obj2 m1]];
  • myMethod1 takes parameter from
    [obj2 m1]
[[obj getObj2] myMethod]

Sending message to itself

[self method];
  • Inside an instance method, self refers to the instance
  • Inside a class mehtod, self refers to the class object

Create a new instance using self

+ (id)createNewInstance
{
    id newInstance = [[self alloc] init];
    return [newInstance autorelease];
}
  • A child can inherit this method but yet manage to create the children class with
    [self alloc]

Sending message to its parent

[super method];

Properties

Getter/Setter method declaration

@interface MyString : NSObject
{
@private
int value;
}
- (int)value;
- (void)setValue:(int)v;
@end

Objective-C provides a mechanism to auto-generate the setter and getter declarations and implementation

  • Use @property to declare getter/setter methods
    MyString.h
    #import <Cocoa/Cocoa.h>
    
    @interface MyString : NSObject {
    @private
        NSString* value;
    }
    @property (retain) NSString* value;
    
    @end
  • Note, the getter and setter methods are yet to be implemented by one of the following ways
    • Use @synthesize to auto-generate the getter/setter implementations
      MyString.m
      @implementation MyString
      
      @synthesize value;
      
      @end
    • @synthesize with the equal sign
      @synthesize value = _value;
    • Equivalent to
    • @interface MyString : NSObject
      {
      @private
      int _value;
      }
      
       
    • @synthesize value;
      
    • Implement the getter/setter manually without the @synthesize
      #import "MyString.h"
      
      @implementation MyString
      
      - (int)value {
          return value;
      }
      - (void)setValue:(int)v {
          value = v;
      }
      
      @end
    • To override the automatic generated methods created by @synthesize
      @implementation MyString
      
      @synthesize myTextArray;
      
      - (void)setMyTextArray:(NSMutableArray *)newArray {
          if (myArray != newArray) {
              [myArray release];
              myArray = [newArray mutableCopy];
          }
      }
      
      @end
  • To access the getter/setter using dot notation
    obj1.value = @"Test value";
    result = obj1.value;

    Call the getter method instead of accessing the instance variable directly

    self.value;

Use a different getter/setter name

@interface MyString : NSObject
{
@private
int internal_value;
}
@property int value;
@end
@implementation MyString
- (int)value {
return internal_value;
}
...
@end

Or

@synthesize value = internal_value;

(retain) instructs the compiler to automatically call retain in the setter method to increment the reference count

@property (retain) NSString* value;

Other options for @property

Make a copy of the input and assign it to v1 in the setter method

@property (copy) NSString *v1;

Make the Objective-C property read only (Create the getter but not the setter)

@property (readonly) NSString *v1;

Retain the input first before the assignment

// Release the old value [value release];
// Retain the new value value = [input retain];
@property (retain) NSString *v1;

Getter and setter does not require to be atomic operation

@property (nonatomic) NSString *v1;
  • atomic provides access to properties in a multi-threaded environment. this getter/setter operation is always atomic and return a full value instead of a transition value

Use multiple attributes in Objective-C property

@property (retain, nonatomic) NSString *v1;

Copy an array object using property require extra coding

@property (nonatomic, copy) NSMutableArray *myTextArray;
  • copy returns a non-mutable version of the collection (Array) only

    To have a mutable array,
    @interface MyString : NSObject {
        NSMutableArray *myTextArray;
    }
    @property (nonatomic, copy) NSMutableArray *myTextArray;
    @end

Dot Notation for Getter and Setter Methods

Objective-C provides special syntax for accessors for getter and setter method to access instance variables

obj1.value = @"Test value";
result = obj1.value;
  • This syntax should limit to getter and setter method only
  • Typically used in properties
obj1.amount += 10;

Setting a class instance within a class through its accessors

self.value = @"Test value";

Objective-C type: id

Objective-C predefined a type id. All objects are essentially of type id.

id result = [NSString string];
  • Any object can be assigned as an id type
  • id type means result can reference/assigned as any type
    id obj1 = [obj2 aMethod];
    [obj1 someMethod];
  • Hence, the compiler will not verified whether an object implements a specific method
    // Will not throw a compilationr error
    [result someNonExistingMethod];

If a return or parameter type isn’t explicitly declared, it assumes type id

- findMyObject:someParam;
- (id)findMyObject:(id)someParam;

Difference between Objective-C NSObject and id

Static typing

  • Declare an object type gives the compiler information about the detail interface of an object
  • For an id type, the compiler cannot determine the interface and will not generate missing method errors until runtime
    NSObject* obj = ...

    NSObject is a static object and a call to a non-existing method will generate a compilation error

    // Will throw a compilation error
    NSObject obj1 = ...
    [obj1 someMethodNotBelongToNSObject];

Create, Initialize and Free Objective-C object

Create and Free Objective-C object

Allocate memory for an Objective-C object

[NSString alloc]

Allocate memory for an Objective-C object and initialize it

NSString* obj1 = [[NSString alloc] init];

Release the object including the memory once it is not used

  • Fail to do it will result in memory leak
    [obj1 release];
  • init may return a different object than the one returned from alloc. Hence call alloc and init in the same line
    NSString* obj1 = [[NSString alloc] init];

Initialize an Objective-C object

Implementation code to initialize an object

- (id) init
{
    if ( self = [super init] )
    {
        [self setValue:@"Set Default Value"];
    }
    return self;
}
  • Call the parent initializer and initialize to self
  • use 'if' to make sure a valid object is returned
    self = [super init]
  • init return an id type
  • Assign self to the value returned by init because the initializer may return an object different from the original receiver
- (id) init
{
   // Do not use the setter method self.someInstanceVariable = ...
   someInstanceVariable = [[NSString alloc] init];
   ...
}
  • The alloc method increments the reference count
  • If the init method use a setter method to set the instance variable, the reference count will increase by 1 again

Objective-C Custom Initializer

Custom init method should start with init

- (id) initWithCount:(int)count
NSString* obj1 = [[NSString alloc] initWithCount:30];

Calling another init method within the init method

- (id)initWithValue:(NSValue *)data {

    // init method may return a new object
    // assign the new object back to the self
    self = [super initWithValue:data];
    if (self) {
        value = [data retain];
    }
    return self;

Add error handling code

- (id)initWithValue:(NSValue *)data {

    // release itself if data is nil
    if (value == nil) {
        [self release];
        return nil;
    }

    self = [super initWithValue:data];
    if (self) {
        value = [data retain];
    }
    return self;

Convenience Constructors

In Cocoa, some class method combines the alloc and init. This is called convenience constructor

NSSTring* s = [NSString sting];

// no need to call [s release];
  • Caller of the convenience constructors does not own the object and therefore no need to call release
  • The convenience constructors usually call autorelease to release the created object once the whole method call chain is completed

Example implementation of Objective-C convenience constructors

+ (id) createNewInstance:(NSString*) value
{
    id newInstance = [[self alloc] init];
    [newInstance setValue:value];
    return [newInstance autorelease];
}

Free an Object-C object (De-allocate)

De-allocate an objective-C object

- (void) dealloc
{
    [value release];
    [super dealloc];
}
  • Release any instance variables if needed
  • Call the parent dealloc
  • dealloc is not called on objects if garbage collection is enabled (Only avaiable for Mac OS X)
  • Otherwise, dealloc is called by the Objective-C runtime in freeing an object
  • When garbage collection is enabled, implement the finalize method