Friday 18 December 2015

UIDatePicker


Sometimes we need  of a date and time picker in our app to pick a date and time . Today I am going to  demonstrate how to use Apple's inbuilt UIDatePicker to pick the date and time. It is very simple.

To use UIDatePicker in an app , first of all create a UIDatePicker instance and set mode as what we want  to have in our picker, only date/time or both. As in my case I want to have both in my app . So i set the mode to  UIDatePickerModeDateAndTime .

//create an  instance of the NSDatePicker
UIDatePicker  *datePicker = [[UIDatePicker alloc] initWithFrame: CGRectZero];

//set mode
[datePicker setDatePickerMode:UIDatePickerModeDateAndTime];


Then add a selector to the date picker that will be called when user want to select the date and time from  datePicker .

//add target

[datePicker addTarget:self action:@selector(selectDateAndTime:) forControlEvents:UIControlEventValueChanged];

Thats all, we have configured the datePicker. Now add the datePicker to the control when we want to datePicker to be appeared.
As I want datePicker to be appeared when user tap on a textField, So i add the datePicker to texField's accessory view as:

//add datePicker as accessory view of the textField:
self.txt_Time.inputView = datePicker ;


Now implement the method that we have assigned as a selector to datePicker:

-(void)selectDateAndTime:(UIDatePicker*)picker{
    NSDateFormatter *dateFormatter  = [[NSDateFormatter alloc]init];
    [dateFormatter setDateFormat:@"hh:mm a dd-MM-yyyy "];
     NSString *formattedString = [dateFormatter stringFromDate:[datePicker date]];
     self.txt_time.text = formattedString;
}


That is it. How easy it is. 

Friday 4 December 2015

Fetch user profile data after login into Facebook

It is easy to integrate Facebook  login in an iOS app . To integrate Facebook login , first of all we have to configure out app at developer site of the Facebook and  get and app ID which will be used in Xcode configuration . 

We can follow these easy steps form developer site of the Facebook. 

Here I am emphasizing how to get the user profile data once user is successfully login in an app from Facebook.

Example:  First create an IBAction  for a button to login Facebook. and define the method to login and fetch data.

  
    if ([FBSDKAccessToken currentAccessToken]) {
     // 1 user is already login, handle it.
    }else{
    
     //2 log in to Facebook first time
    FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
    [login
     logInWithReadPermissions: @[@"public_profile",@"email",@"user_about_me"]
     fromViewController:self
     handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
         if (error) {
          
         //3 handle error   
             NSLog(@"Process error %@", error.localizedDescription);
             
         } else if (result.isCancelled) {
             
             NSLog(@"Cancelled");
             
         } else {
        //4login success, proceed next steps
             
             if ([FBSDKAccessToken currentAccessToken])
             {
                 
                 [[[FBSDKGraphRequest alloc] initWithGraphPath:@"me" parameters:@{@"fields": @"picture,name,location, email"}]
                  startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
                      
                      if (!error) {
                          NSLog(@"fetched user:%@", result);
                          
                          //fetch email and profile picture
                          NSString *email = [result objectForKey:@"email"];
                          NSString *user_name = [result objectForKey:@"name"];
                         
                          NSString *pictureURL = [[[result objectForKey:@"picture"]objectForKey:@"data"]objectForKey:@"url"];

                          NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:pictureURL]];
                          
                          
                     }else{
                          NSLog(@"error in fetching user data==%@", error.localizedDescription);
                      }
                  }];
             
             }
            
         }
     }];
    
    }

Now lets describe the above code:

1)We are checking, if user is already login , we don't follow login process.
2)If user is not login through Facebook, then first login him.Here we have to assign some permission that we want to access his profile during login .

      [login logInWithReadPermissions:       @[@"public_profile",@"email",@"user_about_me"]

3) In completion handler, we check for error, cancel of the login process and success of the login and handle accordingly.

4) If login is success,  we get an access token from Facebook . Here we check for access token , if it is , then we fetch the  required data.

Friday 13 November 2015

Animation in iOS

Animations provide fluid visual transitions between different states of your user interface. In iOS, animations are used extensively to reposition views, change their size, remove them from view hierarchies, and hide them. You might use animations to convey feedback to the user or to implement interesting visual effects. 

In iOS creating the sophisticated animations doesn't require to write any drawing code.All the animation's techniques use the built in support of core animation . Both UIKit and Core animation provide support for animation .

The following UIView properties can be animated:

1) frame
2) bounds
3) backgroundColor
4) center
5) transform
6) alpha
7) contentStretch

Changing the value of these properties merely  update the properties without any animation. To animate such a change we must change  the value of these properties from animation block. 

To understand any concept properly , example is the best way to demonstrate, so here is a simple example:

Assuming we have a single View application , that contains the login form: 

userName -- UITextFiled
password -- UITextField

LogIn -- UIButton

In starting set the initial position of the view to outside the screen


-(void)viewWillAppear:(BOOL)animated{
    super.viewWillAppear(animated)
    
    username.center.x -= view.bounds.width;
    password.center.x -= view.bounds.width;

  }

In ViewDidAppear add the following code:

 -(void)viewDidAppear:(BOOL)animated{
UIView.animateWithDuration(0.5, animations: {
      // self.password.center.x += self.view.bounds.width;  
       self.username.center.x +=  self.view.bounds.width;
    })

To animate the field in we call the UIView class  method animateWithDuration(_:animations:).The animation starts immediately and animates over half a second; you set the duration via the first method parameter in the code.

We can also delay the animation:

UIView.animateWithDuration(0.5, delay: 0.6, options: nil, animations: {
        
        self.username.center.x +=  self.view.bounds.width;

    }, completion: nil)


The class method you use this time looks familiar, but it has a few more parameters to let you customize your animation:
  1. duration: The duration of the animation.
  2. delay :The amount of seconds UIKit will wait before it starts the animation.
  3. options: A bitmask value that allows you to customize a number of aspects about your animation. You’ll learn more about this parameter later on, but for now you can pass nil to mean “no options.”
  4. animations :The closure expression to provide your animations.
  5. completion: A code closure to execute when the animation completes; this parameter often comes in handy when you want to perform some final cleanup tasks or chain animations one after the other.

Animation Options:
options allow to customize the animation:

Repeating :
  •  .Repeat: Enable this option to makes your animation loop forever.
  • .Autoreverse:  Enable this option only in conjunction with .Repeat; this option repeatedly plays your animation in forward then in reverse.

    UIView.animateWithDuration(2.5, delay: 0.9, options: .Repeat | .Autoreverse , animations: {
        self.password.center.x += self.view.bounds.width
        }, completion: nil)
  }
  

Animation Easing:

To make animation more realistic, we use easing options:

You can choose from four different easing options:
  • .Linear: This option applies no acceleration or deceleration to the animation.
  • .CurveEaseIn : This option applies acceleration to the start of your animation.
  • CurveEaseOut:This option applies deceleration to the end of your animation.
  • .CurveEaseInOut:This option applies acceleration to the start of your animation and applies deceleration to the end of your animation.
   UIView.animateWithDuration(2.5, delay: 0.9, options: .Repeat | .Autoreverse | .CurveEaseIn , animations: {
        self.password.center.x += self.view.bounds.width
        }, completion: nil)
  }


References:         https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/AnimatingViews/AnimatingViews.html

Friday 6 November 2015

Print from an app

Hello,  here I am describing the different way to include printing functionality  in an iOS app .
To add printing support in an app, at a high level we create  a print job, providing either an array of ready to print images and pdf documents, a single image or pdf, an instance of built in print formatter classes or custom print page renderer.

The UIKit API includes eight classes and one formal protocol. There are two ways to include printing in an iOS app:

1) using UIActivityViewController :  This provides simple printing and do not provide any control over printing process.

2) using UIPrintInteractionController: The shared instance of this class provides the ability to specify what should happen when printing. It contains the information about the printjob(UIPrintInfo), and the size of the paper, and the area for the printed content(UIPrintPaper). It can have a reference to UIPrintInteractionControllerDelegate protocol.

To add the priting content , UIPrintInteractionController provides following ways:

1) printngItem:  to print single image or pdf document, set the printingItem property of the UIPrintInteractionController.

2) printingItems : an array of images or documents, set the printingItems property of the UIPrintInteractionController.

3) PageRenderer : provides the complete control over the page layout. To include pageRenderer, we first subclass the PrintPageRenderer and the assign the instance of it to the PrintPageRenderer property of the UIPrintInteractionController.

These properties are mutually exclusive.

The general workflow to support printing in an app is as follows:

1) get the shared instance of  UIPrintInteractionController.

2) (optional) Create a UIPrintInfo object, set attributes such as output type, job name, and print orientation; then assign the object to the printInfo property of the UIPrintInteractionController instance.

3) (optional)Assign a custom controller object to the delegate property.

4) set the one of the four property of the UIPrintInteractionController instance.

5) If the current user- interface idiom is ipad, present the printing interface to the user by calling:
      presentFromBArButtonItem:animated:completionHandler:  or
 
     presentFromRect:inView:animated:completionHandler:

If the idiom is iPhone or iPod touch, call
    presentAnimated:completionHandler:

Example:

1) In custom view controller conform the protocol UIPrintInteractionControllerDelegate

2) get the shared instance of UIPrintInteractionController:
 
     UIPrintInteractionController *printController = [UIPrintInteractionController sharedPrintController];

3) create a print job and assign it to the printInfo property of the UIPrintInteractionController instance.


          printController.delegate = self;
        
        //print info object to supply required info to prinController
        UIPrintInfo *printInfo = [UIPrintInfo printInfo];
        
        printInfo.outputType = UIPrintInfoOutputPhoto;
        printInfo.jobName = @"Print Template";
        
        //  printing info to printController

        printController.printInfo = printInfo;

4) set the pritingItem property of the UIPrintInteractionController instance.
     
     printController.printingItem = [UIImage imageNamed:@"jery1.jpeg"];

5) create a block :

   //create block to handle error
        
        void(^ completionHandler)(UIPrintInteractionController *, BOOLNSError*)=
        ^(UIPrintInteractionController *pic, BOOL completed, NSError *error){
            
            if (!completed && error) {
                NSLog(@"FAILED! Due to error in domain %@ with error code %ld", error.domain,(long)error.code);
            }
        };
6) check for userinterface and present accordingly:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
            NSLog(@"user interface is ipad");
            
        }else{
     [printController presentAnimated:YES completionHandler:completionHandler];
}

7) implement the delegate method;

- (void)printInteractionControllerDidFinishJob:(UIPrintInteractionController *)printInteractionController{    
    
    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Print Template" message:@"Your template is ready to pickup" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    
    [alert show];
    
}


Print Directly:

Alternatively we can print directly without presenting the printing user interface. iOS 8 provides a way to do this. To direct print, conform to the UIPrinterPickerControllerDelegate,  and add the following code:

-(void)searchPrinters{
   
    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) {
        UIPrinterPickerController *printerPicker = [UIPrinterPickerController printerPickerControllerWithInitiallySelectedPrinter:nil];
        
        [printerPicker presentAnimated:YES completionHandler:^(UIPrinterPickerController *printer, BOOL userDidSelect,NSError * error){
         
            if (userDidSelect) {
                [UIPrinterPickerController printerPickerControllerWithInitiallySelectedPrinter:printer.selectedPrinter];
                
            printerURL = printer.selectedPrinter.URL;
                
                NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
                
                [defaults setObject:[printerURL absoluteStringforKey:@"printerURL"];
                
                [defaults synchronize];
            }
            
        }];
    }
}

-(IBAction)print:(id)sender{

NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
                
                    self.selectedPrinter = [UIPrinter printerWithURL:[NSURL URLWithString:[defaults objectForKey:@"printerURL"]] ];
                
                    if (self.selectedPrinter) {
                        
                        [printController printToPrinter:self.selectedPrinter completionHandler:^(UIPrintInteractionController *printController, BOOL completed, NSError *error){
                        
                            if (completed) {
                                NSLog(@"priting successfully completed");
                                UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Print" message:@"Successfully printed" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nilnil ];
                                
                                [alert show];
                            }
                            else{
                                NSLog(@"error occured while printing");
}

}




Reference:https://developer.apple.com/library/ios/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/Printing/Printing.html

Friday 30 October 2015

NSOperationQueue and NSOperation

GCD is a lightweight way to represent units of work that are going to be executed concurrently. You don’t schedule these units of work; the system takes care of scheduling for you. Adding dependency among blocks can be a headache. Canceling or suspending a block creates extra work for you as a developer! .

NSOperationQueue and NSOperation add a little extra overhead compared to GCD, but you can add dependency among various operations. You can re-use operations, cancel or suspend them. NSOperation is compatible with Key-Value Observation(KVO) .

NSOperationQueue regulates the execution of a set of NSOperation objects . After being added to queue an operation remains in the queue until it is explicitly  canceled or finishes it  executing its task .
We can add inter operation dependencies among operations  which provide absolute execution order for operations even if  those operation located in different operations queues .
An operation object is not considered ready to execute until all of its dependent operation have finished executing .
Operations are always executed on a separate thread, regardless of  whether they are designated as asynchronous or synchronous .

NSOperation is an abstract class we use to encapsulate the code and data associated with a single task . We subclass it or use one of the system defined subclasses (NSInvocationOperation or NSBlockOperation) to perform actual task.
An operation executes its task once and can't be used to execute again .

To create a customize operation , follow these steps : 
1) Subclass NSOperation .
2) Override main .
3) Create an autoreleasepool in  main .
4) Put your code in autoreleasepool .

The reason we should create our own autorelease pool is that we do not have access to the autorelease pool of the main thread, so we should create your own.

example:
#import <Foundation/Foundation.h>

@interface MyOperation: Operation
@end

@implementation MyOperation

-(void)main{
      @autoreleasepool{
       //define task here
       NSLog(@"custom operation");
      }
}
}
@end

NSOperationQueue API:
1) To get a queue use:
   NSOperationQueue *myQueue = [NSOperationQueue alloc]init];
   myQueue.name = @"queueName";

2) Maximum number of concurrent operations: To set maximum number of operations that  NSOperationQueue can run concurrently .
   myQueue.MaxConcurrentOperationCount = 2;

3) To add operation to queue :
   [myQueue  addOperation:customOperation] ;

4) To pause a queue :
  [myQueue setSuspended:YES];

   To resume , set the setSuspended to NO .
5) To cancel operation in a queue:
   [myQueue cancelAllOperations];

NSOperation API:

1) To make an operation dependent on other operation:

   lets assume op1 and op2 are two custom operation object .
 [op2 addDependency op1];

2) To set the priority of the operation :

[op1 setQueuePriority:NSOperationQueuePriorityVeryLow];

3) To set completionBlock :

[op1 setCompletionBlock: ^{
   NSLog(@"operation has completed).
}];
 

Friday 16 October 2015

Key Value Coding and Key Value Observer

Key-value coding is a mechanism for accessing an object’s properties indirectly, using strings to identify properties, rather than through invocation of an accessor method or accessing them directly through instance variables.
Key-value observer is a  mechanism for observing the changes in the property of an object .

To understand these concepts properly let do some code:

1) start a new singleView iOS project and create a new class named Person .
2) In Person.h define some properties as:

@property (nonatomic, strong) NSString *name;
@property (nonatomic) NSUInteger age;
@property(nonatomic,strong) Person * person;

3)Now initialize  these property with initial values in Person.m

4) In ViewController.m , define private properties as :

@interface ViewController ()
@property(nonatomic,strong) Person * person1;
@property(nonatomic,strong) Person * person2;


@end

5)In ViewDidLoad() method, initialize the person:
    self.person1 = [[Person alloc]init];
    
    [self.person1 setValue:@"Yash" forKey:@"name"];
    [self.person1 setValue:[NSNumber numberWithInteger:25] forKey:@"age"];

    self.person1.person = [[Person alloc]init];
    [self.person1 setValue:@"rajeev" forKeyPath:@"person.name"];

That's how we have set the value of the properties using KVC .


To observe the changes in properties we have to set the observer for the object for which we are observing and implement the method observingValueForKeyPath:

6)In ViewWillAppear() method add these lines:

[self.person1 addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
[ self.person1 addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];

[self.person1 setValue:@"Jeet" forKey:@"name"];
[self.person1 setValue:@"rajeev" forKey:@"name"];

Here we set the observer self(ViewController), and make some change to the name property of the Person  

7) Now implement the method that will be called as changes occurs in the Person's properties .

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    
   if ([keyPath isEqualToString:@"name"]) {
            NSLog(@"the name of person is changed");
            NSLog(@"%@",change);
        }
   if ([keyPath isEqualToString:@"age"]) {
        NSLog(@"the age of person is changed");
        NSLog(@"%@", change);
     }
}

Here we just print the change to the console . We can handle the changes as per our requirements .