Skip to main content

Deep Diving Objective-C Properties (Part 1)

Properties

Properties in objective c are a convenient way to provide the accessors (getter and setter) for instance variable in objective - c language. Let suppose you have a mobile then what are its properties?

Name:
Brand Name:
Screen Size:
etc.

So properties define the things. In a similar manner properties in objective - c define the class or objects.
A Simple Example for a Person class with the basic attribute.

Example: 



@interface Person : NSObject

@property NSString* name;

@end


Compiler will generate 
a getter and setter for you with the following convention:


- (void) setName:(NSString*)name{
    //Compiler generated the code for getter property
}
- (NSString*)name{
    
   //Compiler generated the code for getter property


}


From the above code there are some questions raised in mind?

1) What is the name of instance variable in the above case?
2) How is the memory management will happen for the instance variable?

We go one by one first let us know the name of instance variable in above case:

Binding Instance variable with Properties:

Let suppose you declare the property name as given below:

@interface Person : NSObject

@property NSString* name;

@end


There are three ways to bind the instance variable with the above properties:

1) Declare and Manually Synthesis a Instance Variable

It is the conventional method we used in objective - c to bind a instance variable with properties. We need to declare a instance variable and then synthesis it with the properties.

Person.h


@interface Person : NSObject{
    NSString*       _name;
}

@property NSString* name;

@end

Person.m



@implementation Person

@synthesize name = _name;

@end


In above case we specify that the instance variable "_name" to be bind with the property "name". Similarly we can specify any other name for the property.

Note:  If property and instance name is same like "name" then we can specify the following in case of synthesis.


@implementation Person

@synthesize name;

@end


Done :).

2) Automatic Synthesis (Xcode 4.4 and above)

Above Xcode 4.4 version it has capability to auto synthesis the properties. You just need to declare the property name as explain above. Compiler will automatically create an instance variable matching with the property and synthesis it.


It simulates the following thing for you:


@synthesize name = _name;


Your instance variable will be the same name of the property with a prefix "_" underscore. You do not need to write synthesize in this case and no need to declare the variable. Just declare the property and can directly use the instance variable in init method like following:

Person.h


@interface Person : NSObject

@property NSString* name;

@end

Person.m


@implementation Person

- (instancetype) init{
    self = [super init];
    _name =  [[NSString alloc] initWithFormat:@"property"];
    return self;
}

@end

Done :).

3) Dynamic or Manual Setter and Getter


Dynamic behavior is most tough one for developer ;). In this we need to implement accessors method. So you need to handle memory management code for the instance variable.

Person.h


@interface Person : NSObject{
    NSString*       _name;
}

@property NSString* name;

@end

Person.m



@implementation Person

@dynamic name;

- (NSString*) name{
    return _name;
}

- (void) setName:(NSString *)name{
    //Write Code for store the value in _name and it should be according to memory management.
    //Explain later
}

@end


That is all about binding the instance variable with the properties. Now let move to memory management.

Memory Management With Properties:

Memory handling of instance variable when used through properties are depend upon object lifetime qualifiers:

1) Strong
2) Retain
3) Copy
4) Assign

5) Weak

Strong:


This qualifier is used to take ownership of the object. In Strong it only shallow copy the object. So pointers referencing to the same memory address.

Person.h


@interface Person : NSObject{
    NSString*       _name;
}

@property (strong) NSString* name;


@end

RootViewController.m


@implementation RootViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSString* myName = [[NSString alloc] initWithFormat:@"Test"];
    [_testPerson setName:myName];

}

@end



In MMR Environment it is your responsibility to send the release message in both the cases. In person class dealloc method and in root view controller in the end of view did load method.

In ARC Environment Complier will automatically place the release call for you in both the cases. So main point is both object is owner of test string. So both need to release that.
Retain:
Retain is identical to strong. There is no such difference between retain and strong. Apple introduced a new qualifier with ARC that is Strong. But it has no difference from retain.

Strong and Retain:


In this case both objects person and root view controller share the same memory reference. So it is like a two person watching the same thing.


Copy:

Copy qualifier is also used to take ownership of object. It has some differences from the strong or retain. In some case it provided you deep copy except Collection classes. Both the object has own copy of string object in above case.
@interface Person : NSObject{
    NSString*       _name;
}

@property (copyNSString* name;


@end

RootViewController.m


@implementation RootViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSString* myName = [[NSString allocinitWithFormat:@"Test"];
    [_testPerson setName:myName];

}

@end

It is like two persons watching the different things but belong to same domain (Different object of same type).




Note: In case of collection class this will be not deep copy as the elements in the collection shared by both the owner. If you need to apply this on your custom class then you need to adopt NSCopying protocol. Based on the implementation by you it will be deep or shallow copy.

Weak:

Weak qualifier does not claim ownership of object. So a weak reference remains until there is any strong reference to that object. So once all the strong reference is vanished the weak reference automatically becomes the nil.

@interface Person : NSObject{
    NSString*       _name;
}

@property (weakNSString* name;


@end

RootViewController.m


@implementation RootViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSString* myName = [[NSString allocinitWithFormat:@"Test"];
    [_testPerson setName:myName];

}

@end



In ARC once the view did load method of root view controller is executed then the name in person class will be nil.

Assign:


It is similar to weak but there is subtle difference between the both. In case of assign when all the strong reference vanished the reference will not be nil. It will still point to the same memory address. So it will point to a garbage value. Your Test engineer come to you with random crash ;).

Undefined Behaviour:





Assign is recommended only for primitive data type like int, float etc. Do not use it with objects.


This post covered about lifetime qualifier for properties. This Post will be continue and we will see other qualifier like atomic, Non atomic with examples.


Comments

Popular posts from this blog

iOS8 UIWebView Remove or Modify Keyboard Toolbar

Remove Toolbar: One of my client requirements is to remove the default toolbar for the keyboard. I found numerous examples for iOS7 to remove toolbar from the keyboard window. But it did not work for iOS8. So i came to following solution after some Research on Google: Step1:   First we need to add observer for keyboard notification: [[ NSNotificationCenter defaultCenter ]  addObserver : self selector : @selector ( removeKeyboardTopBar :) name : UIKeyboardWillShowNotification object : nil ]; Step 2: We need to implement the method for observer: - ( void )removeKeyboardTopBar {     } Step 3: Find the keyboard window from all the application  windows:   - ( void )removeKeyboardTopBar {     UIWindow *keyboardWindow = nil ;     UIView * toolBarContainer = nil ;     NSArray * windows = [[ UIApplication sharedApplication ] windows ];     for ( U...

Implement orientation modes in iPhone Hybrid Applications

Let suppose you are working on a hybrid application which runs only in single (portrait) mode. One day a requirement come that PDF and Doc Viewer (HTML Page) should support both (landscape, portrait) mode. Your Application loads all the HTML content from the local html files and you need to implement the above functionality only for one HTML file. Let break the above task in the modules: Step 1: Application should detect when the PDF and Doc viewer is open in application. I setup location.href tag in html to " docvieweron:// " and " docvieweroff:// " when page is open and closed respectively. In this way I am getting a delegate callback in web view: WebViewDelegate: - ( BOOL ) webView:( UIWebView *)webView shouldStartLoadWithRequest:( NSURLRequest *)request   navigationType: ( UIWebViewNavigationType )navigationType {          NSString * urlString = [[request URL ] absoluteString ];...

Blocks are Objective-C Objects !!!

Blocks Blocks are executable code just like a function.  It can be written inside a function or we can store the reference in a variable and call it later.  But wait a minute these all functionality we can achieve by function pointer and functions.  Then what is so special about blocks? Let first go through how we can define blocks. int (^sum)( int , int ) = ^( int number1, int number2){ return number1+number2; }; The above block can be used to find the sum of two numbers.  If we recall the function pointer in c then it is very much similar to above: int sumFunction ( int number1, int number2){ return number1+number2; } int (*sum) ( int , int ) = sumFunction; //Function Pointer *sum Then Why we need Blocks if we already have Function pointer?  1) B locks can capture variables from the enclosing scope by simply referring to them within the block. How ? Let see the next Section 2)  Blocks...