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

Asynchronous Request with NSOperationQueue

Today post is about how to run a asynchronous task in NSOperationQueue.  Generally we do not run a Asynchronous task in NSOperationQueue. It is also not recommended for any programmer to do that. This post is only for learning purpose what will happen if we schedule a asynchronous task in a queue and how can we complete that task:). So let us move to the learning: NSOperationQueue: In iOS NSOperationQueue is a class, which provide a way to perform operation concurrently. We also have others way to perform concurrent operation: 1) GCD 2) NSThread 3) pThread NSOperationQueue is a wrapper on GCD, which provides a very convenient way to execute operation concurrently. To create a Queue for Operation you have to simply allocate a object of the class: NSOperationQueue * opertionQueue = [[ NSOperationQueue alloc ] init ]; For this post let suppose you are making a queue to handle all Http request in your application. So i want to create a queue in Handl...

NSThread with Asynchronous Request

NSThread: It is class used in Cocoa framework to create a thread.You have to specify a target and selector to create a new thread in objective c. So the selector or method is main entry point of your thread.  Detail: What happen once the thread execute all the code in the method (Thread main routine)? Thread is terminated after execute all the code in the entry(its main routine) routine. So how we can run an asynchronous request on NSThread ? What is Async request? It is non blocking request which permit the application to do other task side by side as request is in continue. So it enhance parallelism in the application. Now question is how we can prepare a asynchronous request in iOS: - ( void ) startAsyncRequestWithUrl:( NSString *)urlString{     assert (urlString != nil && urlString. length > 0 );     NSURL * url = [[ NSURL alloc ] initWithString :urlString];     NSURLRequest * urlRequest = [[ NSURLReq...

Shake Effect in iOS

Animation Animation always capture the user attention. We can use animation to update things on the screen.  For developer also animations fascinated things to learn and implement. Today we will try shake effect with Various  API. CABasicAnimation: Here we animate view's frame y coordinate from one position to another position. It is simple example of changing the position with respect to time. CABasic Animation is deal with the single keyframe.                                        y(t) = y 0 + t*d(y) You can use CABasic Animation if you have to play with single value. You need to move object from  one position to another without any intermediate steps. CABasicAnimation * shakeAnimation = [CABasicAnimation animationWithKeyPath: @ "position" ]; shakeAnimation . duration = 0.05 ; shakeAnimation . autoreverses = YES; shakeAnimation . repe...