Pages

Sunday 29 June 2014

Programming in Swift [Basic]

Swift is a new programming language introduce by Apple at WWDC 2014. This language supports iOS7+ and you can integrate Swift with Objective-C and vice versa. 

I am covering Swift in three parts: Basic, Intermediate, and Advance.  This post is all about basic of Swift Programming language. 

Its a brand new language and to learn this you don't require prior knowledge of Objective-C, but basics knowledge of C programming and Object Oriented Programming required. To execute Swift code you need latest version of development IDE (Xcode 6).


Playground

      We are going to use new document type ".playground" to experiment with Swift. Its supported by Xcode 6. Playground allow you to write/edit the swift code and see the result immediately side by side. 

Xcode create a playground for cocoa by default, you can create iOS playground through File --> New --> File --> iOS/Source/Playground. Cheers!! now you have a playground to play with Swift. Playground comes with some default code, it saying Hello playground, now delete the line starting with var keyword, We will discuss var latter in this tutorial. 

As usual say "Hello" to playground by printing a string. 



    println("Hello Playground")


Can you  see the "Hello Playground" message in right pan? No right!! Okay so to see the result, you need to open the console output pan (View --> Assistant Editor --> Show Assistant Editor). In third pan you can see the "Hello Playground" message. Okay! so what is the use of second pan? It shows value of variables and expressions. So whatever you print or draw comes under console pan.


Constants & Variables

      You can use "let" keyword to create constants and "var" keyword to create variables. I have created two variables below :


    //constant 
    let minimumPrice = 18.5//Double type

    //Variables
    var myVariable = 42 // Inter type
    var blogName = "Coding for Bugs" //String type


You have just created one constant as "minimumPrice" and two variables: "myVariable" is of type Integer and "blogName" is of type String. Wait we have not given any type, how swift is deciding the type of variable? Okay so swift infer the type of variable from its value. So as soon as you assign any variable a number, its become Int. If you assign string its become string, and so on...

Swift is a type safe language, that means you can't assign a int value to a String variable. So once type is infer you can't change the type of variable by assigning another type of value. If you will do so, It will be reported as compile time error.

As you know Swift infer the type itself but you can also give the desire type to a variable or constant at time of declaration, this is known as Type Annotation. For example lets create one Double and String variable. 



    var price: Double = 13.0 //Swift infer floating number to Double by default

    var helloMessage: String = "Hello reader"


The colon(:) in declaration means of type so that above declaration can be read as: 
    Declare a variable called price that is of type Double.
    Declare a variable called helloMessage that is of type String.

Semicolons

      “Unlike many other languages, Swift does not require you to write a semicolon (;) after each statement in your code, although you can do so if you wish.”

Data types in Swift

  • Int Its used for whole numbers. Ex: var num: Int = 32
  • Float Its used for numbers with decimal points. Ex: var fNum: Float = 32.1
  • Double Its used for bigger numbers with decimal points. Ex: var dNum = 32.6374
  • String Its used for ordered sequences of characters. Ex: var pi = "π",
       var name: String = "you name"
  • Bool Its used for true or false. Ex: var isRead: Bool = false
  • Array Its used for collection of same type data. Ex: let array = String[]()
  • Dictionary Its used for collection of same type data and key.         Ex: let emptyDictionary = Dictionary<String, Float>()
  • Tuple Its used for collection of objects of any type. Use () to create tuple.
         
    Ex: var HTTP404Error = (404, "Not Found")

Tuples

      Tuples group multiple values into a single compound value. The values in tuples an be of any types and don't have to be of the same type. This is the primary difference between Array and Tuples.


    // 1. Creating tuple
    let http404Error = (404, "Not Found") //type is (Int, String), and equals (404, "Not Found")”

    // 2. Accessing elements of tuple
    let (statusCode, statusMessage) = http404Error
    println("The status code is \(statusCode)") //String interpolation: use \() to insert any value in string
    println("The status message is \(statusMessage)")

    // 3. Ignoring any element in tuple, Use underscore "_" to ignore any value
    let (justTheStatusCode, _) = http404Error
    println("The status code is \(justTheStatusCode)")

    //4. Accessing individual element values in tuple using index number
    println("The status code is \(http404Error.0)")
    println("The status message is \(http404Error.1)")

    // 5. Naming individual elements in a tuple when tuple defined
    let http200Status = (statusCode: 200, description: "OK")
    println("The status code is \(http200Status.statusCode)")
    println("The status message is \(http200Status.description)")


In above code we have created two tuples named as http404Error and http200Status.and in other parts we have used first tuple in different ways. 

1. The (404, "Not Found") tuple groups together an Int and a String to give the HTTP status code two separate values: a number and a human-readable description. It can be described as “a tuple of type (Int, String)”.

2. We have decompose tuple in different constant named as status code and status message. We have inserted value of those constant in string using String Interpolation.

3. We have used _ to ignore second element "status message" of tuple. 

4. We have use elements index number to access their value. Index start from 0.

5. We have given names to individual elements of tuple. These name helps us in accessing individual elements. 

NOTE: don't forget to see the log by opening console(opt + cmd + enter)


String Interpolation

      Its include the name of a constant or variable as a placeholder in a longer string, and to prompt Swift to replace it with the current value of that constant or variable. Wrap the name in parentheses and escape it with a backslash before the opening parenthesis. Ex. println("The status message is \(statusMessage)")

Optionals

      Optionals variable either contains a value or does not contain any value at all. For example lets say you have a string value and you are trying to convert it to number/ Int. It not possible that every string can be converted into an integer. Thats why swift toInt method of String class return an optional value. 

    let possibleNumber = "123"
    let convertedNumber = possibleNumber.toInt()


Because the toInt method might fail, it returns an optional Int, rather than an Int. An optional Int is written as Int?, not Int. The question mark indicates that the value it contains is optional, meaning that it might contain some Int value, or it might contain no value at all.

If you will try to print or use a optional value directly then it might lead to a crash because it might be nil. It means no value. Swift nil is different from Objective-C nil. In case of Objective-C its a pointer to nil but in Swift nil is not a pointer. Simply it is the absence of a value of a certain type. 

Note: Optional of any type can be set to nil not only Object type.

Unwrapping Values of optionals:    
     You can use an if statement to find out whether an optional contains a value. If an optional does have a value, it evaluates to true; if it has no value at all, it evaluates to false.

Once you’re sure that the optional does contain a value, you can access its underlying value by adding an exclamation mark (!) to the end of the optional’s name. The exclamation mark effectively says, “I know that this optional definitely has a value; please use it.” This is known as forced unwrapping of the optional’s value:



    if convertedNumber {
        println("\(possibleNumber) has an integer value of \(convertedNumber!)")
    } else {
        println("\(possibleNumber) could not be converted to an integer")
    }


If you try to use ! to access a non-existent optional value triggers a runtime error. Always make sure that an optional contains a non-nil value before using ! to force-unwrap its value.

Using if else each time is boring and time consuming So swift has introduce a new concept call Optional binding, that we can use to Unwrap the value. Optional Binding is used to find out whether an optional contains a value, and if so, to make that value available as a temporary constant or variable. Optional binding can be used with if and while statements to check for a value inside an optional, and to extract that value into a constant or variable, as part of a single action.



    if let actualNumber = possibleNumber.toInt() {
        println("\(possibleNumber) has an integer value of \(actualNumber)")
    } else {
        println("\(possibleNumber) could not be converted to an integer")
    }
    // prints "123 has an integer value of 123


It will execute else part when it is not possible to convert the given string into a number. 

Operators

      Swift supports all Objective-C operators where some of them are modified and others same as objective-C. Its also support operator overloading that we will discuss in Advance tutorial of this series. 

All arithmetic operator are same as C except reminder operator (%). Now reminder operator work with floating point and negative number. Ex: 8 % 2.5   // equals 0.5 and -9 % 4   // equals -1 

Increment, decrement, unary minus, logical, and compound assignment operator as same as C. 

Swift supports all C based comparison operator and also introduced two new comparison operator (=== and !==). Which you use to test whether two object references both refer to the same object instance.

Range Operator 
   Swift includes two range operators, which are shortcuts for expressing a range of values:

  1. Closed Range Operator(a...b)
         The  closed range operator (
    a...b) defines a range of values that runs from a to b, and include a and b.
  2. Half-Closed Range operator(a..<b)
        Half-closed range operator (
    a..<b) define a range of values thats run from a to b but does not include b. Thats why its called half-closed range. See the below example: 


    for index in 1...5 {
        //here index is of type Int. No need to write var before index
        println("\(index) times 5 is \(index * 5)")
    }
    // 1 times 5 is 5
    // 2 times 5 is 10
    // 3 times 5 is 15
    // 4 times 5 is 20
    // 5 times 5 is 25

    //If you change above range to Half-Closed(1..<5) then it will only up to 20.



Control Flow

      Swift supports all control flow statement of Objective-C with a huge modification in Switch statement. Its also change the way we write conditions, Now we don't need to write brackets () around the condition you can directly write the condition followed by flower braces {}. Examples:



    // If else  conditions
    var a = 2
    var b = 6
    if a > b {
        println("Yes!! \(a) is not greater than \(b)")
    } else {
        println("No!! \(a) is greater than \(b)")
    }

    //while loop 
    while a != b {
        a += 2
        println("a incremented to \(a)")
    }



Switch Statement
      In swift switch statement has below changes 
  • No need to write break statement. Swift is smart enough to break out of matched case.
  • Body of each case must contain at least one executable statement. to ignore any case use break statement.
  • Multiple matching can be separated by comma. Ex: case 2,3,4: .
  • Switch value can be matched against any built in type: Int, Double, String, Tuple, Range.
  • switch statement must be exhaustive. Using default case is easy way to get rid of this condition. 


    let count = 3_000_000_000_000 //you can use _ in number to make it redable
    let countedThings = "stars in the Milky Way"
    var naturalCount: String
    switch count {
    case 0,1:
        naturalCount = "very few"
    case 2...3:
        naturalCount = "a few"
    case 4...9:
        naturalCount = "several"
    case 10...99:
        naturalCount = "tens of"
    case 100...999:
        naturalCount = "hundreds of"
    case 1000...999_999:
        naturalCount = "thousands of"
    default:
        naturalCount = "millions and millions of"
    }
    println("There are \(naturalCount) \(countedThings).")
    // prints "There are millions and millions of stars in the Milky Way.


In above example we are matching a number and commenting about number of stars. In case first we are trying to match multiple values against some value to switch. In rest of conditions we we are trying to match switch value against range of value. 

Without the default statement this switch will not become exhaustive  because its not matching all possible value of count. Thats means every possible value of the type being considered must be matched by one of the switch case.

Switch and Tuple: We can also use tuple to test multiple value in switch statement. You can also bind the elements of tuple to variable or constant. See below example:



    let somePoint = (1, 1)
    var comment:String

    switch somePoint {
    case (0, 0):
        comment = ("(0, 0) is at the origin")
    case (_, 0):
        comment = ("(\(somePoint.0), 0) is on the x-axis")
    case (0, _):
        comment = ("(0, \(somePoint.1)) is on the y-axis")
    case (-2...2, -2...2):
        comment = ("(\(somePoint.0), \(somePoint.1)) is inside the box")
    case (let x, let y):
        ("(\(x), \(y)) is outside of the box")
    }


Above code will print "(1, 1) is inside the box" and in above switch statement we have not used default statement, because without that our switch statement is . If you wish to use default you can replace case (let x, let y) by default statement and replace x and y with indexes of individual elements. 

Thats it, in basic. In next part we will discuss Collections, Functions, Class, Closures etc.
Thanks for reading!! Please do not forget to leave your valuable comments. Bye Bye !!

Sunday 24 February 2013

Introduction to Modern Objective C

Hello friends!! In this post I am going to talk about Modern Objective C. It comes with Xcode 4.5 and it is a feature of LLVM Copiler 4.0 so if you don't have Xcode 4.5, then please update your Xcode to latest version. This tutorial assume that you have prior knowledge of Objective C, if you don't know Objective C then you can start here Objective-C Programming Guide.

         Modern Objective C does not introduce any new construct but it simplify the common Objective C programming pattern, makes program more concise and avoids making common mistakes. More frankly it improve the safety of  container creation. 

Now lets start with some coding and see all the feature introduce in Modern Objective C. First create a project using xcode and name it as  "ModernOBJCTest".

1. File --> New Project --> Single View Application --> On Screen Instruction


Property Synthesis


    In Modern Objective - C you do not need to synthesize the properties, xcode will do it for you. So now you can say bye, bye to "@synthesize" keyword.

  • Name of instance variable in default synthesis will be underscore ('_') prefixed 
  • You need to define the name of instance variable if you are defining custom accessor and setter

Private Methods


    Till now what are you doing for private methods? Have you defined it in interface file(.h file) Yes!! no no... its not a good idea, sorry but please read the basic of OOPs, if No, you are a good programmer and i think you have defined it in category YES!! its cool but now forget it too, because you can write your private methods in implementation file (.m file) without declaring it in interface file or in a category. Thanks to xcode you don't have to worry about order of methods because at time of compilation xcode buffers the body of methods and looks for signatures. For example check the codes under number literals.

NSNumber Literals


       We use NSNumber class to wrap scaler(signed and unsigned short, char, int, long, long long, float, double, BOOL) values in Objective C Object. All scaler values also known as boxed values.

Lest go-ahead and create a method in "MOBJCViewController.m" as follows - 

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    [self numberLiteral];
}

- (void)numberLiteral {
    NSNumber *n1 =@41; // equivalent to [NSNumber numberWithInteger:41];
    NSLog(@"Integer number = %i",[n1 integerValue]);
    
    NSNumber *n2 = @34.234; // equivalent to [NSNumber numberWithFloat:34.234];
    NSLog(@"Float number = %.2f",[n2 floatValue]);
    
    NSNumber *n3 = @31U; // equivalent to [NSNumber numberWithUnsignedInt:31U];
    NSLog(@"Unsigned Int = %u",[n3 unsignedIntegerValue]);
    
    NSNumber *n4 = @3456688876LL;//equivalent to [NSNumber numberWithLongLong:3456688876];
    NSLog(@"Long Long Value = %lld",[n4 longLongValue]);
       
}

      Now hit the run command and see the log in Xcode debug area -

LOG (Shift + Command + Y)
Integer number = 41
Float number = 34.23
Unsigned Int = 31
Long Long Value = 3456688876

In Modern Objective C any bool, char, numeric literal prefixed with '@' character will be evaluated to a pointer to an NSNumber object initialized with that value. Compiler will automatically take care of type of variable.

BOOL Literals


      Similar to number literals you don't need to use NSNumber class methods to convert BOOL values in number, just put '@' before YES and NO. Lets check in code, now create boolLiterals methods and call it from viewWillAppear: method as follows -

- (void)boolLiterals {
    NSNumber *numberYes = @YES;
    NSLog(@"value of numberYes = %d",[numberYes boolValue]);//1 means YES and Zero means NO
}

Check Xcode console, you will find 1 as value of 'numberYes'. Similarly you can create a number literal by assigning any character NSNumber *c = @'c';.
Note: NSNumber literals only support literal scalar values after the '@' that means you can write  @41, @YES, @'c' but not @INT_MIN because compiler translate your code as NSNumber *n1 = [NSNumber numberWithInteger: 41] and so-on .


Array Literals


           Array literals enable you to create NSArray in very less amount of code. No need to use the class methods to create the array. Array created using literal are immutable(you can not add or remove items from resulting array). Lets write code to create an array of friend and say hello to all.
- (void)sayHelloToFriends:(NSArray*)friends {
    for (int i = 0; i<friends.count; i++) {
        NSLog(@"Hello %@!!",friends[i]);
    }
}

In modern objective c, you can acces a particular element without using objectAtIndex: method. If you have completed the above method then call it in viewWillAppear: method of view controller as follows.

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
//is array literals supported by compiler?
#if __has_feature(objc_array_literals)
    //Cheers!! literals are supported
    //create array using literals 
    NSArray *friends = @[ @"Joe", @"Kevin", @"Amit", @"Deepthi" ];
    NSLog(@"Array is created using literal");
#else
    //literals are not supported use old method
    
    NSArray *friends = [NSArray arrayWithObjects:@"Joe", @"Kevin", @"Amit", @"Deepthi",nil];
    NSLog(@"Array is created using NSArray class method");
#endif
    
    //call sayHelloToFriends: method and pass array of friends 
    [self sayHelloToFriends:friends];
}


We are checking availability of array literals by "__has_feature" check. Now RUN the application and check the output in log -

OUTPUT
Array is created using literal
Hello Joe!!
Hello Kevin!!
Hello Amit!!
Hello Deepthi!!

HOW ITS WORK?
When you create number or array using literals then compiler generates code for you. Compiler will generate following code for above array -

 //first holds your all items
 id objects[] = {@"Joe", @"Kevin", @"Amit", @"Deepthi"};
 //calculate number of items
 NSUInteger count = sizeof(objects)/ sizeof(id);
 //create array using class method
 friends = [NSArray arrayWithObjects:objects count:count];


Dictionary Literals


       Personally I love dictionary literals because it simplifies the the process of creating a dictionary and code is easy to understand and read. Lets create a dictionary using literals-

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    //create a dictionary @{key:object, key:object}
    
    NSDictionary *person = @{
    @"name"     : @"Mithilesh Kumar",
    @"age"      : @22,
    @"email"    : @"talkmithilesh123@gmail.com",
    };

    [self printDictionary:person];
}

- (void)printDictionary:(NSDictionary*)dictionary {
    // Person details
    NSLog(@"NAME : %@",[dictionary objectForKey:@"name"]);
    NSLog(@"AGE : %d",[dictionary[@"age"] integerValue]);
    NSLog(@"EMAIL : %@",[dictionary objectForKey:@"email"]);
}

Have you notice the new way to access object from dictionary [dictionary[@"age"] integerValue] Yes!! you can access the object without using instance method objectForKey: .

NOTES: All container created using literals are immutable and you can not create constant using literals  static NSArray *arr = @[]; compiler will generates error. If you want to create constant using literals, use +(void)initialize  class method.

Object Subscripting


        Any Objective - C object can be used with subscript ( [ ] ) operator. By default objective C compiler support subscripting for NSArray and NSDictionary for example -

    NSMutableArray *array = [NSMutableArray arrayWithObjects:@"First",@"Second", nil];
    NSUInteger idx = @2;
    id newObject = @"New-Second";
    id oldObject = array[idx];
    array[idx] = newObject;         // replace oldObject with newObject
    
    NSArray *keys = @[@"one", @"two"];
    NSArray *values = @[@"First", @"Second"];
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObjects:values forKeys:keys];
    NSString *key = @"two";
    oldObject = dictionary[key];
    dictionary[key] = newObject;    // replace oldObject with newObject


You can introduce subscripting in your objects by  implementing following four methods-
  1. - (id)objectAtIndexdSubscript:(NSUInteger)idx
  2. - (void)setObject:(id)object atIndexedSubscript:(NSUInteger)idx 
  3. - (id)objectForKeyedSubscript:(NSUInteger)idx
  4. - (void)setObject:(id)object forKeyedSubscript:(NSUInteger)idx
First two (1 and 2) are used for Array Style Subscripting and last two (3 and 4) are used for Dictionary Style Subscripting. You can implement any set of methods as your requirement. Actually when we use subscripts with array or dictionary objects then compiler translate that in above methods calls. For Example NSArray only implement - (id)objectAtIndexdSubscript:(NSUInteger)idx. Lets write a simple SongList class to see the Array Style subscripting -  

Add a class (Subclass of NSObject) and replace the code by following code

SongList.h

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

@interface SongList : NSObject {
    NSMutableArray *list;
}

- (Song*)objectAtIndexedSubscript:(NSUInteger)idx;
- (void)setObject:(Song*)song atIndexedSubscript:(NSUInteger)idx;

@end


SongList.m

#import "SongList.h"

@implementation SongList

- (id)init
{
    self = [super init];
    if (self) {
        list = [[NSMutableArray alloc] init];
    }
    return self;
}

- (Song*)objectAtIndexedSubscript:(NSUInteger)idx {
    return ((Song*)list[idx]);
}
- (void)setObject:(Song*)song atIndexedSubscript:(NSUInteger)idx {
    list[idx] = song;
}
@end

To test the above code first create a "Song" class with a property called "name" and then import both these classes in viewController class and then replace the viewDidLoad: method and check the log -

- (void)viewDidLoad
{
    [super viewDidLoad];
 
    SongList *sList = [[SongList alloc] init];
    Song *s1 = [[Song alloc] init];
    s1.name = @"song - 1 ";
    sList[0] = s1;
    
    NSLog(@"Song Name is %@",sList[0].name);
    
}



Migrating To Modern Objective - C


        You can migrate your old projects to Modern Objective - C syntax by using Xcode refactor  tool as follows -
  1. Go to Edit menu
  2. Go to Refactor 
  3. Click on Convert to Modern Objective - C Syntax...
  4. Follow on screen instructions
Hey Cheers!! now you have completed almost  every thing related to Modern Objective C. Following table lists all required tools and backward compatibility of Modern Objective C's features - 

compatibility list
You can check updated list here
Hey Guys Thanks for reading!! Please don not forget to leave your valuable comments. Bye Bye !!

Saturday 13 October 2012

integrating facebook and twitter in iOS 6 Apps (Social Framework)

Hello friends!! In this post, i am going to talk about social framework(introduce in iOS6). How to integrate facebook or twitter in iOS6 App.
        Social framework is introduce in iOS6 and by using it we can connect to facebook, twitter or weibo.com, no need of any third party SDKs. To learn social framework in iOS6 you should have Xcode 4.5. Lets start without wasting time first create a single view application and design your first screen as following screen -

Now add Social framework to your project - 
  1. Click on project name in project navigator
  2. Select the project under target in middle pan of Xcode
  3. Make sure that "Build Phases" tab is selected
  4. Expand the "Link binary with libraries", click on triangle
  5. Click on add item(+ button) in left corner of this section 
  6. Search social in search bar (comes after clicking on + button)
  7. Select the "Social.framework" framework and click on "Add" button 

Cheers you have completed the first step of this tutorial. Now import the social framework header file "Social.h" in ViewController.h file of your project.
// import social header file
 #import<Social/Social.h>

Add following two methods to "ViewController.h" file and connect them to respective button's touch event in respective view controller.
 //called on tap of facebook button
 - (IBAction)postOnFacebookButtonTapped:(id)sender;
 //called on tap of tweet button 
 - (IBAction)tweetButtonTapped:(id)sender;


Similarly add body of these two methods in "ViewController.m" file
- (IBAction)postOnFacebookButtonTapped:(id)sender {
}

- (IBAction)tweetButtonTapped:(id)sender {
}


We have added the required framework and methods to our project now it is the time to write the actual code. Social framework provides built in composer (SLComposeViewController), which we can pressent to user with pre loaded text, URL, and images so that user can tweet or post on their timeline. To present the composer we need to create an instance of this class. We can not edit or add any thing to the composer without informing the user. So we must add any initial content before presenting the composer to the user. After presenting the composer, only user can edit the content. 
        
+(SLComposeViewController*)composeViewControllerForServiceType:(NSString*) serviceType  

Above method is use to create the instance of SLComposeViewController and for it we need to pass service type. Service type tells the targeted social website like facebook, twitter and weibo. Service types are as follows -
  • SLServiceTypeTwitter
  • SLServiceTypeFacebook
  • SLServiceTypeSinaWeibo 
You should pass desire service type to create the respective composer. Before creating or presenting the composer we should check the availability of service type  or reachability of site. For this we can use following class method - 

+ (BOOL)isAvailableForServiceType:(NSString *)serviceType

This methods returns BOOL value where NO represents one of following - 
  1. User's twitter or facebook account is not set up on device
  2. Desire site is  not available 
Now lets implement postOnFacebookButtonTapped: method 
- (IBAction)postOnFacebookButtonTapped:(id)sender {
    if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
        SLComposeViewController *fbComposer = [SLComposeViewController
                                               composeViewControllerForServiceType:SLServiceTypeFacebook];
        //set the initial text message
        [fbComposer setInitialText:@"Hi i am coding for bugs!!"];
        //add url
        if ([fbComposer addURL:[NSURL URLWithString:@"www.kmithi.blogspot.com"]]) {
            NSLog(@"Blog url added");
        }
        
        
        // you can remove all added URLs as follows
        //[fbComposer removeAllURLs];
        
        //add image to post
        if ([fbComposer addImage:[UIImage imageNamed:@"strongBinary"]]) {
            NSLog(@"strong binary added to the post");
        }
        if ([fbComposer addImage:[UIImage imageNamed: @"scan.jpg"]]) {
            NSLog(@"scan is added to the post");
        }
        
        //remove all added images
        //[fbComposer removeAllImages];
        
        //present the composer to the user
        [self presentViewController:fbComposer animated:YES completion:nil];
        
    }else {
        UIAlertView *alertView = [[UIAlertView alloc]
                                  initWithTitle:@"Facebook Error"
                                  message:@"You may not have set up facebook service on your device or\n                                  You may not connected to internent.\nPlease check ..."
                                  delegate:self
                                  cancelButtonTitle:@"OK"
                                  otherButtonTitles: nil];
        [alertView show];
    }
}


Yah!! It is this much easy any one can add facebook and twitter to their applications. All methods use to set initial text or add/ remove URLs and images returns BOOL values  where YES tells that successfully added/ removed image or URL.  You can add more than one image but not URL only last URL will be posted to your timeline. If your account is not set up then first set up it (Settings --> facebook) otherwise it will returns NO while checking the availability of service or error while posting. Similarly we can implement  tweetButtonTapped: method-
- (IBAction)tweetButtonTapped:(id)sender {
    if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]) {
        
        SLComposeViewController *twitterComposer = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
        
        //add initial text
        [twitterComposer setInitialText:@"Tweeting from iPhone 5 #TesingApp"];
        
        //present composer
        [self presentViewController:twitterComposer animated:YES completion:nil];
    } else {
        UIAlertView *alertView = [[UIAlertView alloc]
                                  initWithTitle:@"twitter Error"
                                  message:@"You may not have set up twitter service on your device or\n                                  You may not connected to internent.\nPlease check ..."
                                  delegate:self
                                  cancelButtonTitle:@"OK"
                                  otherButtonTitles: nil];
        [alertView show];
    }
}


Composer view controllers looks like follow -





















Now i am going to discussed the last but not least feature of SLComposeViewController class. It is the completion handler. SLComposeViewController class define a block property of type SLComposeViewControllerCompletionHandler. SLComposeViewControllerCompletionHandler takes a parameter of type SLComposeViewControllerResult. Parameter indicate wether user finished or cancelled composing the post. Parameter will be one of following - 
  • SLComposeViewControllerResultCancelled,
       It indicates  that user has cancelled composing the post
  •  SLComposeViewControllerResultDone
       It indicates  that user has finished composing the post 
 //add completion handler
        twitterComposer.completionHandler = ^(SLComposeViewControllerResult result) {
            if (result == SLComposeViewControllerResultCancelled) {
                NSLog(@"User has cancled composing the post, and tapped the cancle button");
            }
            
            if (result == SLComposeViewControllerResultDone) {
                NSLog(@"User has finished composing the post, and tapped the send button");
            }
        };


To know more about block programming check this!
Thanks for reading!! Please leave your valuable suggestions!! Bye Bye !!

Thursday 30 August 2012

iOS Application Directory Structure : Document, Cache and tmp

Hello friends!!

In this post i am going to talk about iOS application directory structure. iOS applications run in sandbox like environment that means Application (A) can not access the resources of Application(B). In more easy words i can say that a closed room is allocated to each Application where they have to eat and sleep, of course  room is closed so they can not access resources of each other. However an Application can request Operating System( OS ) to run other Application. Following image shows directory structure of a typical iOS application.


Apple reserve all rights to change the directory structure and you may find different structure on different OS version for example  "Libarary/ Application Support " does not exists in iOS 5 and older versions. Most important directories are app bundle(myApp.app), Document, cache and tmp. 
             When our Application is installed on iPhone, iTunes creates a home directory(In above image "App" is home directory) for application. This directory is same as closed room(ad discussed above) for the App. It contains everything that Application can access. Applications can create file, delete file under home directory. 
            You should be selective while storing file in directories because wrong selection of directory may affect the iCloud syncing process and waste the user space, that encourage the user to delete your App. So you should be selective to where you place which file.  
           iOS uses a unique ID instead of application name, so you can not give absolute or relative path of any directory. 
Now let me describe the usage of directories and code to access these directories. 

Bundle Directory(myApp.app) -

     This is the place(bundle) where your App exists. You should not modify this directory, it prevent your app from launching again. All resources you put in your project will stored in this directory. How to get the path of bundel directory -
//get the main bundel 
NSBundle *bundle = [NSBundle mainBundle];
//get the path of home directory 
NSString *bundlePath = [bundle bundlePath];
 You can find the path of your resources by appending resource name to bundlePath or  as follows
//Find the path of a image(myPhoto.png)
NSString *pathTomyPhoto = [[NSBundle mainBundle] pathForResource:@"myPhoto" ofType:@"png"];
NSLog(@"\n%@\n",pathTomyPhoto);

OUTPUT-
.../Applications/99C1AFFA-0908-4968-B6C7-E2644385D86D/appName.app/myPhoto.png

To protect this directory from tempering iOS sign it with unique id, any modification in this ID prevent your app from launching.

Document Directory

Use this directory to store important files of your application like sqlite database. Data of this directory is backup in iTunes so don't store temporary and large fiels. If you will store large amount of data in document directory, Apple may reject your App see this. In more general you should store only those data which can not be recreated by your app.  How to get the path of document directory?

/*use following c function to find any directory, just you need to provide the directory type*/
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
//find the actual path
NSString* docDir = [paths objectAtIndex:0];
NSLog(@"\n%@\n",docDir);

Document/Inbox Directory 

This directory is used by other applications to open files with the help of your application. For example email app places email attachement in inbox directory before opening the attachement with the help of your application. We have only read and delete permission on this directory means we can not create new file or edit fiels in this directory. If you want to edit any file, then you must move that file to document or other directory. You can access this directory by adding a path component "Inbox" to document directory path.

Library Directory

This directory is used to store app specific files. Content of this directory is also backup in iTunes but not exposed to user. You should not store user specific files in directory. iOS applications are not permitted to use this directory although you can use the subdirectories of this directory. 

NOTE: data of cache directory is not backup in iTunes. 

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libDirectory = [paths objectAtIndex:0];
NSLog(@"%@",libDirectory);

Library/Caches Directory

Content of this directory is not backup by the iTunes. You should store only those files which can be recreated easily. System may delete content of this directory (to free up the disk space) when it is required, so your app should gracefully handel this type of situations  Eligible candidate of this directory are downloadable contents, database cache files etc . You can create, edit, delete content of this directory. You can get the path of cache directory as follows -
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachesDirectory = [paths objectAtIndex:0];
NSLog(@"%@",cachesDirectory);

Library/Application Support Directory

This directory was introduced in iOS 5.0.1 and content of this directory is also backup in iTunes. You can use this directory to store App created fiels, templates for example we can store newly purchased levels of game in this directory. You can find the path of this directory by passing "NSApplicationSupportDirectory" as searchPathDirectory in "NSSearchPathForDirectoriesInDomains" method.

Library/Preferences Directory

Apple recommend us to not create any file in this directory and instead of this we should use "NSUserDefault" class to set and get preference values of our APP. Purpose of this directory is to store app preference files, generally our app creates files in this directory. You can set preference values in user default as follows -
//get user default object
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
    
//set values in user default
[userDefault setValue:@"mithi" forKey:@"nickname"];
[userDefault setBool:NO forKey:@"shoulShowDOB"];
[userDefault synchronize];
    
//get values from user default
NSString *nickName = [userDefault valueForKey:@"nickname"];
NSLog(@"Nickname = %@",nickName);
BOOL shouldShowDOB = [userDefault boolForKey:@"shoulShowDOB"];
    
if (shouldShowDOB) {
    NSLog(@"We have permission to show DOB");
}else {
    NSLog(@"We do not have permission to show DOB");
}

tmp Directory

Last but not least tmp directory is use to store temporary files, you should use this directory to store those files which are not required to persist or required for a few time. You should delete the files when that is not required. Content of this directory can be deleted any time. You can get the path of this directory as follows -
NSString *tmpDirectory = NSTemporaryDirectory();
NSLog(@"%@",tmpDirectory);

Don't forget to leave your valuable comments!! bye bye!!