Tuesday, January 22, 2013

Timer Countdown in iPhone Tutorial

Hola,, iCoder,, RDC is here

What's up guys, today we are going to learn one simple but important concept in iPhone application development.. Time Countdown using NSTime Class.

At the end of this Tutorial you can find Complete Source code zip file.

So stay with me, and do it step by step by .. don't forget to drop me a message or comment.



Note : This Application Developed Using : iOS 6. , Xcode 4.6, and MAC OS X Lion 10.8.3

PHASE - I (Create New Project)

So, Let's Fire Xcode!!

Go to File --> New --> Project

Now we can see a Pop up Window for selecting our application templet 

So make sure you select Application in iOS option on your Left hand side.
then select Single View Application as shown in below picture and Go for Next..



In the Next Window we need to put Our Project Details this way

 --------------------------------------------------------------
| Product Name : TimerDemo |
| Organization Name :RDCWorld |
| Company Identifier : com.rdcworld           |
| |
| Class Prefix :  (leave it blank for now) |
| |
| Devices : iPhone |
 --------------------------------------------------------------

Note : Don't forget to Make Tick mark on "Use Automatic Reference Counting" option.



Go to Next --> Create.

Now you can see Xcode default dashboard with our newly created project .

PHASE - II (Design UI)

We need to add one UITextField, and few UIButtons on our screen to get it work.

So, Just open ViewController.xib file you can see default blank layout

1. Let's drag UINavigationBar from Object library double click on it and give title as  "Countdown Timer", (we will use this for just showing app Title)

2.  Select main view and change background to Purple Colour or what you like or leave it as default.

3. Drag one UILabel from Object Lib and update its text => Timer Status , and expand its width as shown in screen shot.

4. now add Three UIButtons, give them names as Start, Pause,and Reset.

see below screen shot.



PHASE - III (Create IBOutlet and IBActions)

We are going to create IBOutlet for UITextField,UILabel and IBAction method for UIButton.

Okay, Now select Assistant Editor on Top Right side



You can see our ViewController.xib (Left side) + ViewController.h (Right side) opened together.

1. Fist is First, Create IBOutlet for UITextField,UILabel

Hold Ctrl button--> Select UILabel named "Timer Status" --> drag cursor to ViewController.h(right side) file, when your cursor is between @interface and @end.

while leaving cursor here you will get Popup Window 

just put Name : "timerLabel" and click on Connect.



now you can see below code line in your ViewController.h file (in right side)

@property (weak, nonatomic) IBOutlet UILabel *timerLabel;

do the same for UITextField, and UIButtons (one by one) give the name "timerValueTextField", "startButton", "pauseButton" and "resetButton" respectively.

after adding IBOutlet for all you can see IBOutlet property added to your header file.

@property (weak, nonatomic) IBOutlet UITextField *timerValueTextField;
@property (weak, nonatomic) IBOutlet UIButton *startButton;
@property (weak, nonatomic) IBOutlet UIButton *pauseButton;
@property (weak, nonatomic) IBOutlet UIButton *resetButton;


2. Create IBAction methods
2.1 Select UIButton (which says -'Start') --> Right Click on it 

2.2 Click on Touchup Inside in  "Sent Events" option and drag cursor just below to new created IBOutlets, and put the method name "startTimer" in pop window



you can see IBAction method added in header file 

- (IBAction)startTimer:(id)sender;

2.3 do the same for next two Buttons and give methods name as "stopTimer", and "resetTimer" respectively.

this time you can see three new  IBAction methods created in header file

- (IBAction)stopTimer:(id)sender;
- (IBAction)resetTimer:(id)sender;


Done!! now back to Standard Editor



PHASE - IV (Writing Code)

~ ~ ~ ~ ~ ~ ~ ~ ~              Controller Class (ViewController)          ~ ~ ~ ~ ~ ~ ~ ~ ~  


1. open ViewController.h

2. declare an integer for Timer Value

int secondsLeft;

3.  create NSTimer instance with property

@property (nonatomic, weak) NSTimer *timer;

4. just before @end add one IBAction method to handle keypad go

- (IBAction)keypadGoBack:(id)sender;

So Finally our ViewController.h file look like

-----------------------------------------------------------------------------------------------------------------------------------------
//
//  ViewController.h
//  TimerDemo
//
//  Created by RDC on 22/01/13.
//  Copyright (c) 2013 RDC World. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController{
    int secondsLeft;
}
@property (nonatomic, weak) NSTimer *timer;

@property (weak, nonatomic) IBOutlet UILabel *timerLabel;
@property (weak, nonatomic) IBOutlet UITextField *timerValueTextField;
@property (weak, nonatomic) IBOutlet UIButton *startButton;
@property (weak, nonatomic) IBOutlet UIButton *pauseButton;
@property (weak, nonatomic) IBOutlet UIButton *resetButton;

- (IBAction)startTimer:(id)sender;
- (IBAction)stopTimer:(id)sender;
- (IBAction)resetTimer:(id)sender;
- (IBAction)keypadGoBack:(id)sender;
@end
-----------------------------------------------------------------------------------------------------------------------------------------

Now come to ViewController.m file , open it

Here is the Heart of Application

1. To create Timer Countdown, we need to create NSTime class object with some properties like Time interval and the selector  method so we can handle any action with Timer.

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(runScheduledTask:) userInfo:nil repeats:YES];

 Here we have 1 second time interval, and selector method name "runScheduledTask"

2. also we need to provide body for selector method

- (void)runScheduledTask: (NSTimer *) runningTimer {    
    int hours, minutes, seconds;
    secondsLeft--;
    hours = secondsLeft / 3600;
    minutes = (secondsLeft % 3600) / 60;
    seconds = (secondsLeft %3600) % 60;    
    timerLabel.text =[NSString stringWithFormat:@"Time Remaining %02d:%02d:%02d", hours, minutes, seconds];    
    if (secondsLeft==0) {        
        [timer invalidate];        
        timerLabel.text = @"Time up!!";        
    }
}

3. we can stop Timer using Invalidate 

[timer invalidate];


So Finally our ViewController.m file look like

-----------------------------------------------------------------------------------------------------------------------------------------
//
//  ViewController.m
//  TimerDemo
//
//  Created by RDC on 22/01/13.
//  Copyright (c) 2013 RDC World. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@end

@implementation ViewController

@synthesize timer;
@synthesize timerValueTextField;
@synthesize timerLabel;
@synthesize pauseButton;
@synthesize startButton;
@synthesize resetButton;

- (void)viewDidLoad{
    [super viewDidLoad];
    [pauseButton setEnabled:NO];
    [resetButton setEnabled:NO];    
}

- (void)didReceiveMemoryWarning{
    [super didReceiveMemoryWarning];    
}

- (void)runScheduledTask: (NSTimer *) runningTimer {    
    int hours, minutes, seconds;
    secondsLeft--;
    hours = secondsLeft / 3600;
    minutes = (secondsLeft % 3600) / 60;
    seconds = (secondsLeft %3600) % 60;    
    timerLabel.text =[NSString stringWithFormat:@"Time Remaining %02d:%02d:%02d", hours, minutes, seconds];    
    if (secondsLeft==0) {        
        [timer invalidate];        
        timerLabel.text = @"Time up!!";        
    }
}

- (IBAction)startTimer:(id)sender {
    [pauseButton setTitle:@"Pause" forState:UIControlStateNormal];    
    secondsLeft = [timerValueTextField.text intValue];    
    // This will allow 10,000 Hours Timer Limits
     if (secondsLeft >0 && secondsLeft <36000001 ) {        
        timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(runScheduledTask:) userInfo:nil repeats:YES];
        [startButton setEnabled:NO];
        [pauseButton setEnabled:YES];
        [resetButton setEnabled:YES];
    }
    else{                
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"Please! enter valid timer value" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [alert show];       
    }
}

- (IBAction)stopTimer:(id)sender {    
    if ([@"Pause" isEqualToString:[pauseButton titleForState:UIControlStateNormal]]) {
        NSLog(@"Paused");
        [pauseButton setTitle:@"Resume" forState:UIControlStateNormal];        
        [startButton setEnabled:NO];
        [pauseButton setEnabled:YES];
        [resetButton setEnabled:NO];        
        if (timer != nil) {
            [timer invalidate];            
            int hours, minutes, seconds;
            hours = secondsLeft / 3600;
            minutes = (secondsLeft % 3600) / 60;
            seconds = (secondsLeft %3600) % 60;            
            timerLabel.text =[NSString stringWithFormat:@"Time paused at %02d:%02d:%02d", hours, minutes, seconds];           
        }        
    }
    else{
        NSLog(@"Resumed");
        [pauseButton setTitle:@"Pause" forState:UIControlStateNormal];
        [startButton setEnabled:NO];
        [pauseButton setEnabled:YES];
        [resetButton setEnabled:YES];        
        timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(runScheduledTask:) userInfo:nil repeats:YES];        
        if (secondsLeft==0) {            
            NSLog(@"Time up!!");            
            [timer invalidate];
            timerLabel.text = @"Time up!!";            
        }
    }    
}

- (IBAction)resetTimer:(id)sender {
    [startButton setEnabled:YES];
    [pauseButton setEnabled:NO];
    [resetButton setEnabled:NO];    
    [pauseButton setTitle:@"Pause" forState:UIControlStateNormal];
    if (timer != nil) {
        [timer invalidate];
        timerLabel.text = @"Timer got reset!!";
    }else{
        NSLog(@"timer is nil");
    }    
    timerValueTextField.text=@"";    
}

-(IBAction)keypadGoBack:(id)sender{
    [timerValueTextField resignFirstResponder];
}
@end
-----------------------------------------------------------------------------------------------------------------------------------------

~ ~ ~ ~ ~ ~ ~ ~ ~              Application Delegate Class (AppDelegate)          ~ ~ ~ ~ ~ ~ ~ ~ ~  


Make sure your AppDelegate file code should be default 

Finally our AppDelegate.h file look like 

-----------------------------------------------------------------------------------------------------------------------------------------
//
//  AppDelegate.h
//  TimerDemo
//
//  Created by KNSMac2 on 22/01/13.
//  Copyright (c) 2013 RDC World. All rights reserved.
//

#import <UIKit/UIKit.h>

@class ViewController;

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) ViewController *viewController;

@end
-----------------------------------------------------------------------------------------------------------------------------------------


Finally our AppDelegate.m file look like 

-----------------------------------------------------------------------------------------------------------------------------------------
//
//  AppDelegate.m
//  TimerDemo
//
//  Created by RDC on 22/01/13.
//  Copyright (c) 2013 RDC World. All rights reserved.
//

#import "AppDelegate.h"
#import "ViewController.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];    
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

//for now leave rest all empty methods..
@end
-----------------------------------------------------------------------------------------------------------------------------------------

Okay wrap it up this application. let's Run it.
we can Start, Pause, Resume and Stop Timer..



Cheers!! we did it. 

You can find complete project source code zip file here : TimerDemo.zip (67.22 KB)


I Would love to here your thoughts !! 

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;