Saturday, January 12, 2013

Complier Directives in Objective-C


Complier Directives in Objective-C 

@, or "at" sign compiler directives, are as central to understanding Objective-C's gestalt as its ancestry and underlying mechanisms. It's the sugary glue that allows Objective-C to be such a powerful, expressive language, and yet still compile all the way down to C.

Interface & Implementation
1. @class
2. @interface
3. @implementation
4. @end

Instance Variable Visibility
5. @public
6. @private
7. @protected //default
8. @package

Properties
09. @property
10. @synthesize
11. @dynamic

Protocols
12. @protocol
13. @required //default
14. @optional

Exception Handling
15. @try
16. @catch
17. @throw
18. @finally

Object Literals
19. @" string "
20. @42, @3.14, @YES, @'Z'
21. @[ ]
22. @{ }

Objective-C Literals
24. @selector ( )
25. @protocol ( )

C Literals
26. @encode ( )
27. @defs ( )

Optimizations
28. @autoreleasepool { }
29. @synchronized { }

Compatibility
30. @compatibility_alias


Now Details with Definition and Example

Interface & Implementation

1. @class  : Used for class forward declarations. 
        Declares the names of classes defined elsewhere without having to import the class' header file.

Forward Class Declarations : Occasionally, @interface declarations will reference an external class in a property or as a parameter type. Rather than adding #import statements for each class, it's good practice to use forward class declarations in the header, and import them in the implementation.

Example. if I want to use MyClass data In my MyViewController class. So in MyViewController.h file I do like this

#import <UIKit/UIKit.h>

@class MyClass; //or #import "MyClass.h"

@interface MyViewController : UIViewController

@end


Now I have to #import "MyClass.h" in my MyViewController.m File.

Advantages : Shorter compile times, less chance of cyclical references; you should definitely get in the habit of doing this if you aren't already.


2. @interface :  Used to declare of Class / Interface or Category

Class/ Interface Declaration

Example :  File name is "MyClass.h", I have created MyClass using NSObject Base Class

#import <Foundation/Foundation.h>

@interface MyClass : NSObject

@end


Category Declaration

Example : File name is "NSString+MYCustomString.h". I have created MyCustomString Category using NSString Base Class.

#import <Foundation/Foundation.h>

@interface NSString (MYCustomString)

@end


3. @implementation : Used to define a Class / Interface or Category

Class/ Interface Definition

Example :  File name is "MyClass.m", I have implemented MyClass using "MyClass.h" header file

#import "MyClass.h"

@implementation MyClass

@end


Category Definition

Example : File name is "NSString+MYCustomString.m". I have implemented MyClass using "MYCustomString.h" header file

#import "NSString+MYCustomString.h"

@implementation NSString (MYCustomString)

@end


4. @end : Used to indicates ends the declaration, definition of Class/ Interface, Category or Protocols.

Example: We can see in every Class/Protocol/Interface/Category  like blow code

#import "MyClass.h"

@implementation MyClass

@end


Instance Variable Visibility

5. @public : Declares that instance variables as public access to all classes.
6. @private :Declares that instance variables only available in this class.
7. @protected : Declares that  instance variables available in this class and its derived classes as well, it's default property.
8. @package It means the instance variable member is accessible only from the framework in which it is defined. 

Example. In "MyClass.h" file


#import <Foundation/Foundation.h>

@interface MyClass : NSObject {
    
@public
    NSString *firstName;
    NSString *lastName;
    
@private
    NSString *personalID;
    
    @package
    int age;
    
@protected // this is default
    NSString *address;
}

@end

Properties

09. @property : Declares a property of variable with exact behavior of property using property modifiers like strong, weak etc.

Example: In my "MyClass.h" file

#import <Foundation/Foundation.h>

@interface MyClass : NSObject {
    
}

// define variable property
@property NSString *firstName;

//define variable property with exact behavior
@property (nonatomic, retain) NSString *lastName;

@end


@interface MyClass : NSObject{
    float rate;
    NSString *name;
}


10. @synthesize: Tells compiler to automatically generate setter and getter methods for the given property in its header file

Example: In my MyClass.m file

#import "MyClass.h"

@implementation MyClass

@synthesize firstName;
@synthesize lastName;

@end

11. @dynamic : directive essentially tells the compiler "don't worry about it, its setter and getter methods are on the way."

So we use dynamic directive in two situations
a. if we are going to write setter and getter ourselves for adding some extra logic
b. or just tells the compiler that the getter and setter methods are implemented not by the class itself
but somewhere else (like the superclass)

Example:

Super class:
@property (nonatomic, retain) NSButton *someButton;
...
@synthesize someButton;

Subclass:
@property (nonatomic, retain) IBOutlet NSButton *someButton;
...
@dynamic someButton;


Protocols

12. @protocol : Marks the start of protocol declaration.
    Defines a set of methods to be implemented by any class conforming to the protocol, 
as if they were added to the interface of that class.

Example:

@protocol MyProtocol <NSObject>

//declare method here

@end


#import <Foundation/Foundation.h>

@interface MyClass : NSObject

@end

13. @required : Used to declare protocol method implementation is must when a class use adopt this protocol. Protocol methods are required by default.

Example:

@protocol MyProtocol <NSObject>

//this is default (required method)
-(NSString *) getUserName;

@end


#import <Foundation/Foundation.h>

@interface MyClass : NSObject

@end

14. @optional : Used to declare protocol method implementation is optional when a class use adopt this protocol.

Example

@protocol MyProtocol <NSObject>

@required
-(NSString *) getUserName;

@optional
-(NSString *) getUserID;
-(BOOL) isValidUser;

@end


#import <Foundation/Foundation.h>

@interface MyClass : NSObject

@end


Exception Handling

15. @try : defines a block of code that can throw an exception.
16. @catch : define block of code to handle exception thrown by try block, this is usually an NSException object.
17. @finally : defines a block of code that executed whether an exception is thrown or not.

Example:

MyClass *obj = [[MyClass alloc] init];

@try {
    
    [obj noSuchMethod];
}
@catch (NSException *e) {
    
    NSLog(@"The Exception name is %@ and the reason is %@",[e name], [e reason]);
}
@finally {
    
    [obj release];//no use after ARC enabled
}


18. @throw : defines throws an exception object

Example:

NSException* myException = [NSException
                            exceptionWithName:@"IndexOutOfBoundsException"
                            reason:@"Attempted to access an array index that is out of bounds"
                            userInfo:nil];
@throw myException;
// [myException raise]; /* equivalent to throwing the exception, above */


Object Literals

19. @" string " : Declares a content NSString object. Such strings do not need to be retained or released.

Example:

NSString *str = @"This is a constant string.";

20. @42, @3.14, @YES, @'Z'  : Returns an NSNumber object initialized with pertinent class constructor



Example

// character literals.
NSNumber *theLetterZ = @'Z';          // equivalent to [NSNumber numberWithChar:'Z']

// integral literals.
NSNumber *fortyTwo = @42;             // equivalent to [NSNumber numberWithInt:42]
NSNumber *fortyTwoUnsigned = @42U;    // equivalent to [NSNumber numberWithUnsignedInt:42U]
NSNumber *fortyTwoLong = @42L;             // equivalent to [NSNumber numberWithLong:42L]
NSNumber *fortyTwoLongLong = @42LL;   // equivalent to [NSNumber numberWithLongLong:42LL]

// floating point literals.
NSNumber *piFloat = @3.141592654F;    // equivalent to [NSNumber numberWithFloat:3.141592654F]
NSNumber *piDouble = @3.1415926535;   // equivalent to [NSNumber numberWithDouble:3.1415926535]

// BOOL literals.
NSNumber *yesNumber = @YES;           // equivalent to [NSNumber numberWithBool:YES]
NSNumber *noNumber = @NO;             // equivalent to [NSNumber numberWithBool:NO]

21. @[ ] : Returns an NSArray object initialized with the comma-delimited list of objects as its contents.

Example 

NSArray *myArray = @[@"one",@"two",@"three"];

is same as

NSArray *myArray = [NSArray arrayWithObjects:@"one",@"two",@"three", nil];


22. @{ } : Returns an NSDictionary object initialized with the specified key-value pairs as its contents, in the format: @{@"someKey" : @"theValue"}.

Example : 

NSDictionary *myDictionary = @{@"userName" : @"rdc", @"password":@"testPwd"};

is same as

NSDictionary *myDictionary2 = [NSDictionary dictionaryWithObjectsAndKeys:@"userName", @"rdc", @"password",@"testPwd", nil];
//nil to signify end of objects and keys.


23. @( ) : Dynamically evaluates the boxed expression and returns the appropriate object literal based on its value


Example: In my "MyClass.m" file

#import "MyClass.h"

@implementation MyClass

-(void) boxedExpressions{
    
    // numbers.
    NSNumber *smallestInt = @(-INT_MAX - 1)// [NSNumber numberWithInt:(-INT_MAX - 1)]
    NSNumber *piOverTwo = @(M_PI / 2);        // [NSNumber numberWithDouble:(M_PI / 2)]
    
    // enumerated types.
    typedef enum { Red, Green, Blue } Color;
    NSNumber *favoriteColor = @(Green);       // [NSNumber numberWithInt:((int)Green)]
    
    // strings.
    NSString *path = @(getenv("PATH"));       // [NSString stringWithUTF8String:(getenv("PATH"))]
    NSArray *pathComponents = [path componentsSeparatedByString:@":"];
    
}

@end

Objective-C Literals

24. @selector ( method_name ) : Returns the selector type 'SEL' of the given Objective-C method. Generates compiler warning if the method isn’t declared or doesn’t exist.

Example:

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    SEL aMethodSelector = @selector(aMethod);
    
    [self performSelector:aMethodSelector];
    
}

-(void)aMethod{
    
    NSLog(@"aMethod called");
}
@end


25. @protocol (protocol_name ) : Returns a Protocol * pointer to the protocol with the specified name.

For example to check if an object conforms to a protocol. You can then cast it to an object conforming to that protocol so that you can call protocol methods on it, without having to know which kind of class the object is:
Protocol *aProtocol = @protocol(ProtocolName);
if ([sender conformsToProtocol:aProtocol])
{
    id senderWithProtocol = (id )sender;
    BOOL wtf = [senderWithProtocol aProtocolMethod];
}

C Literals

26. @encode ( type_spec) : Returns the character string encoding of a type.

Example:

-(void) aMethod
{
    char *enc1 = @encode(int); /* enc1 = "i" */    
    char *enc2 = @encode(id);  /* enc2 = "@" */    
    char *enc3 = @encode(@selector(aMethod)); /* enc3 = ":" */
    
    /* practical example: */
    CGRect rect = CGRectMake(0, 0, 100, 100);
    NSValue *v = [NSValue value:&rect withObjCType:@encode(CGRect)];
}

27. @defs ( ) : The @defs directive returns the layout of an Objective-C class.

Example:

struct { @defs( NSObject) }

Optimizations

28. @autoreleasepool { } : create autoreleasepool to dealloc real eased objects when execution complete at the end of block.

If your code contains a tight loop that creates lots of temporary objects, you can use the @autorelease directive to optimize for these short-lived, locally-scoped objects by being more aggressive about how they're deallocated. @autoreleasepool replaces and improves upon the old NSAutoreleasePool, which is significantly slower, and unavailable with ARC.

You should not declare a variable inside the @autoreleasepool block.

The @autoreleasepool is about six times faster than using NSAutoreleasePool, therefore Apple recommends its use even for non-ARC projects.

Example:

-(void) aMethod
{
   
@autoreleasepool
    {
       
/* code that creates a large number of temporary objects */
    }
}

29. @synchronized { } : Encapsulates code in a mutex lock. It ensures that the block of code and the locked object can only be accessed by one thread at a time.

Example :

-(void) aMethodWithObject:(id)object
{
    @synchronized(object)
    {
        /* code that works with locked object */
    }
}


Compatibility

30. @compatibility_alias : Allows you to define an alias name for an existing class. The first parameter is the alias for a class name, a class with this name must not exist. The second parameter is the name of an existing class that the alias refers to.

Example : in MyClass.h file

#import <Foundation/Foundation.h>
#import "ExistingClassName.h"

@interface MyClass : NSObject

@end

@compatibility_alias AliasClassName ExistingClassName;

No comments:

Post a Comment