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

What does enable bitcode do in Xcode

Background: Now days compilation process for any language is divided into two parts and same is applicable for objective c. Frontend Compiler (Clang) Backend Compiler (LLVM) Frontend Compiler (Clang):  Responsibility of front-end compiler is to take a source code and convert into intermediate representation (IR).  In case of clang it is LLVM IR.  Backend Compiler(LLVM):  Responsibility of backend compiler is to take a IR as input and convert into object code. LLVM input is bitstream of LLVM IR (Bitcode) and output is sequence of machine instruction(Object code). Each  cpu or processor has different set of  M achine   instruction, So  LLVM output is CPU dependent or it can be executed on specific CPU only.   There may be question in your mind that  1) What is the need to divide into these phases? 2) What is LLVM IR? Can we see the LLVM IR as Output? What is the need to divide into these phases? It is beneficial for both the programming language designer a

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 Handler class

Everything about BLE with iOS Part1 (Introduction)

In this article we will learn how to turn your iPhone to behave as peripheral (who has data to send) or central (who receive the data). What is BLE (Bluetooth Low energy device) ? Bluetooth LE is a wireless personal area network technology like its previous incarnation, Classic Bluetooth. It can be use to transfer and receiving of the data. What is difference between Classic and LE ? BLE has low power consumption and low data transfer rate. BLE can support large number of slaves. On the other hand Classic (3.0) support maximum 7 devices connectivity. Unique feature of BLE is advertising  functionality,  So other devices can scan,  connect and  receive data from the advertising BLE device. Other difference is in classic you need to pair the devices first for the communication. Terms: Peripheral:  It is device which advertise the service. In client-server architecture form we can say peripheral is server which has data to send to client. The basic difference i