Friday, 22 May 2015

Preserve and Restore the state of the App

State Preserving and Restoration Process:
Application state preservation and restoration is all about presenting the user with application continuity in terms of appearance and behavior. The UIKit preservation and restoration system provides a mechanism by which an application is able to save and restore the state of specific view controllers and views between different application invocations. UIKit achieves this by defining a flexible structure to which the application must conform in terms of providing information on what is to be saved, and implementing methods that are called by UIKit at certain points during the preservation and restoration process.

During the application design process, the developer must decide which view controllers and views that comprise the application need to have state preserved to ensure continuity for the user. Each item for which state is to be saved must then be assigned a restoration identifier. 

Note:If a view controller does not have a restoration ID, none of the controller’s child views or view controllers will be saved, irrespective of whether or not those sub-views have a restoration ID.

Preserve the State:
Each time a running application is placed into the background, UIKit will ask the application whether or not it requires state preservation. In the event that the application requires the state to be saved, UIKit will traverse the view controller hierarchy of the application and save the state of each object that has a restoration ID. As it does this, it will call a method on each eligible object in order to provide that object with an opportunity to encode and return additional data to be included in the saved state. Once the state information has been gathered, it is saved to a file on the local file system of the device.

Restore the State:
When the application is next launched (as opposed to being brought out of the background and into the foreground) UIKit will look for a saved state file for the application. In the event that it finds one, it will ask the application if state restoration is required. If the application responds affirmatively, UIKit will use the saved state to guide the application through the process of re-creating the views and view controllers to the previous state.


The application preservation and restoration is controlled by a series of interactions between UIKit, the application Delegate and preserved viewControllers and views as summarized in flow chart;

State Restoration



Example: 
1) In order to implement state preservation and restoration  ,implement the  methods in the application delegate which return a boolean value to indicate whether or not preservation and restoration are required.

-(BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder{
    return YES;
}

-(BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder{
    return YES;

}

2) When UIKit walks the view controller hierarchy of an application to preserve state, only those objects with a restoration ID will be saved.
Restoration IDs can be assigned to objects either in code or from within Interface Builder. The restoration ID can be any valid string and may be assigned in code via the restorationID property of the UIView and UIViewController classes. For example:
myViewController.restorationIdentifier =@"thirdViewController";

3) By default, the following state information is saved and restored automatically for view controllers:
     Currently presented view controller
     Currently selected tab
     State of navigation stacks

In the case of views, the following is preserved by default:
   Current scroll position
   Currently selected cell in a table view
   Current state of an image view (zoom, pan, etc)
   Web history (including scroll position and zoom level)


Saving Additional Information:
4) Some times in we want to save the additional data with object to be saved while preserving the state of the app and restoring.
When the state of a specific view controller is to be saved, it will check to see if a method named encodeRestorableStateWithCoder has been implemented in that object’s class. If the method has been implemented, UIKit will call that method, passing through a reference to an NSCoder object. It is then the responsibility of that method to store any additional state data that needs to be preserved into that NSCoder object before returning. UIKit will then save that NSCoder object along with the rest of the application’s state.

When UIKit restores the view controller object on a subsequent launch of the application, it will call the decodeRestorableStateWithCoder method of that object, passing through the NSCoder object containing the previously stored state data. The method is then responsible for decoding the object and using the data contained therein to restore the view to the previous state.
-(void)encodeRestorableStateWithCoder:(NSCoder *)coder{
    [coder encodeObject:self.txtView.text forKey:@"unsaveText"];
    
    [coder encodeObject:UIImagePNGRepresentation(self.imgView.image)
                 forKey:@"YourImageKey"];
    [super encodeRestorableStateWithCoder:coder];
}

-(void)decodeRestorableStateWithCoder:(NSCoder *)coder{
   self.txtView.text = [coder decodeObjectForKey:@"unsaveText"];
    self.imgView.image = [UIImage imageWithData:[coder decodeObjectForKey:@"YourImageKey"]];
    [super decodeRestorableStateWithCoder:coder];
}

5)Saving General Application State:
There will also be situations where other data may be relevant to the state of the application but not directly associated with the user interface elements. In order to address this need, the following two methods may be implemented within the application delegate class:
  • application:willEncodeRestorableStateWithCoder
  • application:didEncodeRestorableStateWithCoder
The former method is called by UIKit at the start of the preservation process and is passed a reference to an NSCoder object into which state data may be stored. The application:didEncodeRestorableStateWithCoder method, on the other hand, is called when UIKit has completed the restoration process and is passed the NSCoder object into which general state data was previously stored.


References:
http://useyourloaf.com/blog/2013/05/21/state-preservation-and-restoration.html
http://www.techotopia.com/index.php/An_Overview_of_iOS_7_Application_State_Preservation_and_Restoration

Friday, 8 May 2015

share with Facebook from an iOS app


It's amazing to share the experience of one with an app on facebook.  Now it's very easy to integrate social media in iOS app.

To post content, photo or share stories on facebook from an iOS app, Facebook provide the SDK with full support of all the major functionality it have. By using it;s SDK we can directly login to facebook, post data on the timeline or other friends wall and can share the link, photo and posts.


To include these functionality in our app.. some configuration is required.

1) Install the Facebook SDK : Download the latest version of SDK from developers site and install it.

2) Create a facebook app:  First we need to registered as developer on facebook. Then create a facebook  app on developer's site.

and fill in each section for app

  • Bundle ID - iOS Bundle ID that corresponds to your app.
  • iPhone App Store ID - App Store ID.
  • iPad App Store ID -iPad App Store ID if your app is in the store.

3) Configure the Xcode Project:  
     A) Add the SDK for iOS project and add required framework to app.
    
     B)  Edit the .plist file.

       1.Create a key called FacebookAppID with a string value, and add the app ID there.
       2.Create a key called FacebookDisplayName with a string value, and add the Display              Name we  configured in the App Dashboard.
       3.Create an array key called URL types with a single array sub-item called URL Schemes. Give               this a single item with your app ID prefixed with fb.
          This is used to ensure the application will receive the callback URL of the web-based OAuth flow.
4)   In appDelegate.m, add the following code:
               #import <FBSDKCoreKit/FBSDKCoreKit.h>
               #import <FBSDKLoginKit/FBSDKLoginKit.h>
- (BOOL)application:(UIApplication *)application openURL:(NSURL* )url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
    
    return [[FBSDKApplicationDelegate sharedInstanceapplication:application
                                                          openURL:url
                                                sourceApplication:sourceApplication
                                                       annotation:annotation];
}


- (void)applicationDidBecomeActive:(UIApplication *)application {
    [FBSDKAppEvents activateApp];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

return [ [FBSDKApplicationDelegate sharedInstance] application :application
                 didFinishLaunchingWithOptions:launchOptions]
  }


5) Now our project is configured, we can add different functionality  to our app:
    Sharing
    LogIn With Facebook
    App Events
   Graph API calls


To login with facebook, import the required files and add this code

FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
   
[login logInWithReadPermissions:@[@"public_profile", @"email", @"user_friends"] handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
        
          if (error) {
            
       // Process error
        }
         else if (result.isCancelled) {
           
            // Handle cancellations
        } 
          else {
            
            // If you ask for multiple permissions at once, you
            // should check if specific permissions missing
              
                      if ([result.grantedPermissions containsObject:@"email"]) {
                      
                          NSLog(@"%@",result);
                          // Do work
                      }
                }
    }];


To share photo on facebook, your controller must conform to  <FBSDKSharingDelegate> to handle different state in sharing

//build your photo content
   
    FBSDKSharePhoto *photo = [[FBSDKSharePhoto alloc]init];
    photo.image = [UIImage imageNamed:@"tom.jpg"];
    photo.userGenerated = YES;
    
    FBSDKSharePhotoContent *content = [[FBSDKSharePhotoContent alloc]init];
    content.photos = @[photo];
    
    FBSDKShareDialog *shareFB = [[FBSDKShareDialog allocinit];
    
    if ([shareFB canShow]) {
    shareFB.shareContent = content;
    
    shareFB.delegate = self;
    [shareFB show];
    }
    else{
        
        UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"Error" message:@"can't show the share dialog box" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nilnil ];
        
        [alert show];
        
    }

and add the delegate method

#pragma mark === delegate method
- (void)sharer:(id<FBSDKSharing>)sharer didCompleteWithResults:(NSDictionary *)results
{
    NSLog(@"completed share:%@", results);
}

- (void)sharer:(id<FBSDKSharing>)sharer didFailWithError:(NSError *)error
{
    NSLog(@"sharing error:%@", error);
    NSString *message = error.userInfo[FBSDKErrorLocalizedDescriptionKey] ?:
    @"There was a problem sharing, please try again later.";
    NSString *title = error.userInfo[FBSDKErrorLocalizedTitleKey] ?: @"Oops!";
    
    [[[UIAlertView allocinitWithTitle:title message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nilshow];
}

- (void)sharerDidCancel:(id<FBSDKSharing>)sharer
{
    NSLog(@"share cancelled");
}

That's so simple with FBSDK to include the functionality of facebook in our app.