google calendar integration in ios app

95
Google Calendar Integration with iOS App www.letsnurture.com

Upload: ketan-raval

Post on 15-Jul-2015

123 views

Category:

Mobile


0 download

TRANSCRIPT

Page 1: Google calendar integration in iOS app

Google Calendar Integration with iOS App

www.letsnurture.com

Page 2: Google calendar integration in iOS app

www.letsnurture.com

Project Overview

The app we'll build in this tutorial is going to let users get connected to their Google account, download their calendars, and create a new event with a description and a date/time. The new event will be posted to a calendar that the user selects.

Regarding our app structure, the basic view is going to be a table view that will contain three sections for setting the following data:

An event descriptionAn event date/timeA target calendar

Page 3: Google calendar integration in iOS app

www.letsnurture.com

As far as the event description is concerned, a textfield will appear on the cell when the user edits the description and it will go away when he finishes doing so. For ease of use, an Input Accessory View will appear above the keyboard every time that the textfield is displayed.

For setting or changing the event date and time, another view (not a view controller) is going to be used. This view will contain a date picker view, from which the user will be able to pick a date.

An event can be an all-day event, so no specific time needs to be set. For this case, a button will be used to set the date picker contents. For events occurring at a specific time, the date picker will display both date and time. For all-day events, only the date will be displayed. The view that contains the date picker (and a toolbar with the necessary bar button items as well) will be added as a subview to the view of our view controller when the user taps on the row of the second section of the table view.

Page 4: Google calendar integration in iOS app

www.letsnurture.com

Finally, the calendar section is going to be multi-functional. When the user is not yet signed into their Google account, only one row is going to exist in the section with a message that prompts the user to download their calendars. When the user selects this, the authorization process will be put in action.

Once the access token has been obtained, an API call will be made to get the calendar list from Google. After the calendar list has been taken, the first calendar on the list is going to replace the prompting message on the row and become the selected calendar by default.

In addition to all of the above, a toolbar will exist under the table view and it will contain two bar button items. One button will be for posting the event on the selected calendar and a second button will be used to log out.

Page 5: Google calendar integration in iOS app

www.letsnurture.com

1. Create a New Project

Step 1Launch Xcode and create a new project. Select the Single View Application option and click Next:

Page 6: Google calendar integration in iOS app

www.letsnurture.com

In the Product Name field, add the GoogleCalendarPostDemo value. Of course, you may choose another name if you'd like.

Also, make sure to check the Use Automatic Reference Counting option and uncheck everything else. After that, keep on going.

Page 7: Google calendar integration in iOS app

www.letsnurture.com

Finally, select a directory to store the project and click Create.

Page 8: Google calendar integration in iOS app

www.letsnurture.com

Step 2Now you need to add the class files that were implemented in the previous tutorial. This class is going to be the mechanism that will do all the work behind the scenes. So, if you have the previous tutorial's project files, get these two:

GoogleOAuth.hGoogleOAuth.mAdd them into your project. If you don't have the previous project, then you can download and get them from this post's download.

Page 9: Google calendar integration in iOS app

www.letsnurture.com

2. Building the Interface

We will use Interface Builder to setup the interface. As you will soon find out, several subviews are going to be added because we want to make the demo app as functional as it can be. Here is a series of steps that describe every subview you should add, along with the properties for each one:

Open the ViewController.xib file to configure the interface and to add all the necessary subviews. First of all, set the view's Size to None in the Utilities Pane > Attributes Inspector > Simulated Metrics, in order to let the project work properly on iPhones prior to the 5.

Page 10: Google calendar integration in iOS app

www.letsnurture.com

Set the view's Background Color to White.

Drag-and-drop a UIToolbar subview into the view. Place it at the bottom of the screen.

Add the following items on the toolbar (ordered left-to-right):Bar Button Item with Title: Sign outFlexible Space Bar Button ItemBar Button Item with Title: Post

Add a UITableView subview on the view and let it occupy all the available space left on the view.

Set the next two properties of the table view:Style: GroupedBackground:: Clear Color

Page 11: Google calendar integration in iOS app

www.letsnurture.com

Page 12: Google calendar integration in iOS app

www.letsnurture.com

Next, we need to have another view that will contain the date picker view. Here are the steps:

Add a new view outside of the default view and set its Size to None (like you did before). Also, set its Height to 460.

Set the view's Background Color to Scroll View Textured Background Color.

Add a UIDatePicker subview in the view and center it in accordance to the view's center.

Add a UIToolBar subview at the bottom of the view.

Add the following bar button items to the toolbar:Bar Button Item with Title: CancelFlexible Space Bar Button ItemBar Button Item with Title: All-day eventFlexible Space Bar Button ItemBar Button Item with Title: Okay

Page 13: Google calendar integration in iOS app

www.letsnurture.com

Page 14: Google calendar integration in iOS app

www.letsnurture.com

Finally, add the following subviews outside the default view controller's view and in the second view we just created:

A UIToolBar subview. This is going to be the Input Accessory View for the textfield that will be used to edit the event description. Add the next bar button items to it:

Bar Button Item with Title: CancelFlexible Space Bar Button ItemBar Button Item with Title: Okay

A UIActivityIndicatorView with the following properties:Style: Large WhiteBackground: Black Color

Page 15: Google calendar integration in iOS app

www.letsnurture.com

3. Setup IBOutlet Properties & IBAction Methods

Step 1We are going to need a few IBOutlet properties connected to our subviews, so we can modify them in code.

To connect an IBOutlet property to a subview (as well as to create an IBAction method), you need to have the ViewController.h file shown in the Assistant Editor.

So, click on the middle button of the Xcode Editor toolbar to let it show up. Make sure that the contents of the ViewController.h file are displayed there.

Page 16: Google calendar integration in iOS app

www.letsnurture.com

I will show you how to create an IBOutlet property for the table view only. Use the same way to create the properties for the subviews I'll tell you about next.

Either on the Document Outline pane or directly on the view, do the following:

1.Right-Click or Control-Click on the table view

2.On the black popup menu, click on the circle next to the New Referencing Outlet option and keep the mouse button pressed.

3.Drag-and-drop (and at the same time a blue line will follow your mouse) into the Assistant Editor window.

Page 17: Google calendar integration in iOS app

www.letsnurture.com

On the new window that appears, add the tblPostData as the Name of the property and don't touch any other options.

Click on the Connect button or hit the Return button on your keyboard.

Here is a list with all the subviews that we need IBOutlet connections created, along with their names. Make sure to follow the same way as before and you'll be fine.

•Post bar button item: barItemPost•Sign out bar button item: barItemRevokeAccess•Input Accessory View Toolbar (the alone toolbar): toolbarInputAccessoryView•View container of the date picker: viewDatePicker•Date Picker: dpDatePicker•All-day bar button item: barItemToggleDatePicker•Activity Indicator View: activityIndicatorView

Page 18: Google calendar integration in iOS app

www.letsnurture.com

Step 2As you see, we added some bar button items in our views. We require from them to react on our taps, so we need to create IBAction methods to make that happen.

Creating an IBAction method is almost the same as I previously demonstrated. For the Post bar button item only, here is the procedure in detail:

On either the Document Outline or directly on the view, right-click or control-click on the bar button item.On the black popup menu, under the Sent Actions section, click on the circle next to the Selector option and keep the mouse button down.Drag and drop on the Assistant Editor window

Page 19: Google calendar integration in iOS app

www.letsnurture.com

On the new window, add the post in the Name field and leave everything else as it is. Click on Connect or hit the Return button on your keyboard.

Now, follow the same pattern and create the next IBAction methods for the given subviews:

•Sign out bar button item: revokeAccess•Okay bar button item on the Input Accessory View Toolbar: acceptEditingEvent•Cancel bar button item on the Input Accessory View Toolbar: cancelEditingEvent•Okay bar button item on the Date Picker View Toolbar: acceptSelectedDate•Cancel bar button item on the Date Picker View Toolbar: cancelPickingDate•All-day bar button item on the Date Picker View Toolbar: toggleDatePicker

Page 20: Google calendar integration in iOS app

www.letsnurture.com

After the addition of all the IBOutlet properties and all the IBAction methods, your ViewController.h file should look like this:

@interface ViewController : UIViewController@property (weak, nonatomic) IBOutlet UITableView *tblPostData;@property (weak, nonatomic) IBOutlet UIBarButtonItem *barItemPost;@property (weak, nonatomic) IBOutlet UIBarButtonItem *barItemRevokeAccess;@property (strong, nonatomic) IBOutlet UIToolbar *toolbarInputAccessoryView;@property (strong, nonatomic) IBOutlet UIView *viewDatePicker;@property (weak, nonatomic) IBOutlet UIDatePicker *dpDatePicker;@property (weak, nonatomic) IBOutlet UIBarButtonItem *barItemToggleDatePicker;@property (strong, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicatorView; - (IBAction)post:(id)sender;- (IBAction)revokeAccess:(id)sender;- (IBAction)acceptEditingEvent:(id)sender;- (IBAction)cancelEditingEvent:(id)sender;- (IBAction)acceptSelectedDate:(id)sender;- (IBAction)cancelPickingDate:(id)sender;- (IBAction)toggleDatePicker:(id)sender; @end

Page 21: Google calendar integration in iOS app

www.letsnurture.com

4. Adopting Protocols

Step 1Now that the interface has been setup and configured and the IBOutlet properties along with the IBAction methods have been created and connected, it's time to start writing some code.

Previously we added the GoogleOAuth header and implementation files in the project, but that's not enough to make our class work. We also need to import it in the view controller's class and adopt its protocol.

Open the ViewController.h file and import the GoogleOAuth.h file at the top of the file:

Page 22: Google calendar integration in iOS app

www.letsnurture.com

Step 2In addition to the GoogleOAuth class' protocol, we need to adopt the following as well:

UITableViewDelegate: the delegate of the table view.UITableViewDatasource: the datasource of the table view.

UITextFieldDelegate: the delegate of the textfield that will be used to edit the event description.

So, while still within the ViewController.h file, modify the @interface statement like this:

@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate, GoogleOAuthDelegate>

Page 23: Google calendar integration in iOS app

www.letsnurture.com

5. Declaring Private Properties & Methods

Step 1There are some properties and some methods that should be declared at the private section of the class and are required to make everything work smoothly.

These properties are mostly going to store application information, but some simple flags will also be used to indicate program state.

The next code snippet presents all the private data members you should add in your project (copy and paste them if you'd like). The comments explain everything. Don't forget that we are working now in the ViewController.m file!

Page 24: Google calendar integration in iOS app

www.letsnurture.com

@interface ViewController () // The string that contains the event description.// Its value is set every time the event description gets edited and its// value is displayed on the table view.@property (nonatomic, strong) NSString *strEvent; // The string that contains the date of the event.// This is the value that is displayed on the table view.@property (nonatomic, strong) NSString *strEventDate; // This string is composed right before posting the event on the calendar.// It's actually the quick-add string and contains the date data as well.@property (nonatomic, strong) NSString *strEventTextToPost; // The selected event date from the date picker.@property (nonatomic, strong) NSDate *dtEvent; // The textfield that is appeared on the table view for editing the event description.@property (nonatomic, strong) UITextField *txtEvent;

Page 25: Google calendar integration in iOS app

www.letsnurture.com

// This array is one of the most important properties, as it contains// all the calendars as NSDictionary objects.@property (nonatomic, strong) NSMutableArray *arrGoogleCalendars; // This dictionary contains the currently selected calendar.// It's the one that appears on the table view when the calendar list// is collapsed.@property (nonatomic, strong) NSDictionary *dictCurrentCalendar; // A GoogleOAuth object that handles everything regarding the Google.@property (nonatomic, strong) GoogleOAuth *googleOAuth; // This flag indicates whether the event description is being edited or not.@property (nonatomic) BOOL isEditingEvent; // It indicates whether the event is a full-day one.@property (nonatomic) BOOL isFullDayEvent; // It simply indicates whether the calendar list is expanded or not on the table view.@property (nonatomic) BOOL isCalendarListExpanded; @end

Page 26: Google calendar integration in iOS app

www.letsnurture.com

Beyond that, add the next method declarations after the properties and before the @end statement:

-(void)setupEventTextfield;-(NSString *)getStringFromDate:(NSDate *)date;-(void)showOrHideActivityIndicatorView;

Step 2

After having declared all these properties, let's do some initialization. This will take place on the viewDidLoad: method. Note that in this method we also set self as the delegate and the datasource of the table view.

Page 27: Google calendar integration in iOS app

www.letsnurture.com

- (void)viewDidLoad{    [super viewDidLoad];         // Set self as the delegate and datasource of the table view.    [_tblPostData setDelegate:self];    [_tblPostData setDataSource:self];         // Set the initial values of the following private properties.    _strEvent = @"";    _strEventDate = @"Pick a date...";    _isEditingEvent = NO;    _isFullDayEvent = NO;    _isCalendarListExpanded = NO;         // Initialize the googleOAuth object.    // Pay attention so as to initialize it with the initWithFrame: method, not just init.    _googleOAuth = [[GoogleOAuth alloc] initWithFrame:self.view.frame];    // Set self as the delegate.    [_googleOAuth setGOAuthDelegate:self];}

Page 28: Google calendar integration in iOS app

www.letsnurture.com

6. Table View Datasource & Delegate Methods

Let's keep going by writing some datasource and delegate methods related to the table view. 

For the time being, we'll add only some standard code. As we move on, we'll add even more code when it's required. So, let's go ahead. As I said at the beginning, there are going to be three sections on the table view:

(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{    return 3;}Each section is going to contain one row. For the third section, we'll have as many rows as the calendars support. 

In this method, you can see how the _isCalendarListExpanded flag is used for first time:

Page 29: Google calendar integration in iOS app

www.letsnurture.com

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{        if (section != 2) {        return 1;    }    else{        // Depending on whether the calendars are listed in the table view,        // the respective section will have either one row, or as many as the calendars are.        if (!_isCalendarListExpanded) {            return 1;        }        else{            return [_arrGoogleCalendars count];        }    }}

Page 30: Google calendar integration in iOS app

www.letsnurture.com

Let's add some footer titles, in order to make our demo app more descriptive. Nothing hard here:-(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{    // Set the footer title depending on the section value.    NSString *footerTitle = @"";    if (section == 0) {        footerTitle = @"Event short description";    }    else if (section == 1){        footerTitle = @"Event date";    }    else{        footerTitle = @"Google Calendar";    }         return footerTitle;}

Page 31: Google calendar integration in iOS app

www.letsnurture.com

Set the height of the row for each cell:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{    return 50.0;}Regarding the tableView:cellForRowAtIndexPath: datasource method, this one is going to be built step-by-step while we add more functionalities to the app. For now, let's write only the basics:

Page 32: Google calendar integration in iOS app

www.letsnurture.com

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{    static NSString *CellIdentifier = @"Cell";    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];         if (cell == nil) {        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];                 [cell setSelectionStyle:UITableViewCellSelectionStyleGray];        [cell setAccessoryType:UITableViewCellAccessoryNone];              // Set a font for the cell textLabel.        [[cell textLabel] setFont:[UIFont fontWithName:@"Trebuchet MS" size:15.0]];    }             return cell;}

Page 33: Google calendar integration in iOS app

www.letsnurture.com

Finally, we have only one delegate method, the well-known tableView:didSelectRowAtIndexPath:. 

Just like the previous one, this is also going to be built step-by-step. For now, make it only remove the selection from each row that is tapped:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{    // At first, remove the selection from the tapped cell.    [[_tblPostData cellForRowAtIndexPath:indexPath] setSelected:NO];}

Page 34: Google calendar integration in iOS app

www.letsnurture.com

7. Editing the Event Description

Step 1Until now, I have already said many times that a textfield is going to appear on the table view every time that we want to change the event description. However, when not editing, the textfield should not appear. After we finish editing, we'll update the event description and make the textfield go away.

Before we bring this behavior to life, it might be better to implement the private method that we have declared, the setupEventTextfield. In this method, we'll do the following tasks:

• We will initialize the textfield by setting a frame related to the cell content view's frame and set a style too.

• We'll set the contents of the strEvent string as its text.• Remember the (alone) toolbar we added in the Interface Builder earlier? We'll set it as the input accessory view of the textfield.

• We'll set self as its delegate so we can handle the Return key of the keyboard.

Page 35: Google calendar integration in iOS app

www.letsnurture.com

-(void)setupEventTextfield{    // Initialize the textfield by setting the following properties.    // Add or remove properties depending on your demand.    if (!_txtEvent) {        _txtEvent = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 10.0,                                                                  [[_tblPostData cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]] contentView].frame.size.width - 20.0,                                                                  30.0)];        [_txtEvent setBorderStyle:UITextBorderStyleRoundedRect];        [_txtEvent setText:_strEvent];        [_txtEvent setInputAccessoryView:_toolbarInputAccessoryView];        [_txtEvent setDelegate:self];    }}

Page 36: Google calendar integration in iOS app

www.letsnurture.com

Step 2

Now that this method is ready and we can call it any time we'd like to initialize the textfield, let's see how we can implement the behavior we expect from the table view. 

We want to display the textfield every time that we tap on the row of the first section, so let's do so.

Inside the tableView:didSelectRowAtIndexPath: we'll check if the event is currently being edited. 

If not, then we'll call the previously implemented method to initialize the textfield, we'll change the flag status indicating whether the event is being edited and we'll show the keyboard.

Page 37: Google calendar integration in iOS app

www.letsnurture.com

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{    // At first, remove the selection from the tapped cell.    [[_tblPostData cellForRowAtIndexPath:indexPath] setSelected:NO];         if ([indexPath section] == 0) {        // If the row of the first section is tapped, check whether the event description is being edited or not.        // If not, then setup and show the textfield on the cell.        if (!_isEditingEvent) {            [self setupEventTextfield];        }        else{            return;        }                 

Page 38: Google calendar integration in iOS app

www.letsnurture.com

// Change the value of the isEditingEvent flag.        _isEditingEvent = !_isEditingEvent;        // Reload the selected row.        [_tblPostData reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]                            withRowAnimation:UITableViewRowAnimationAutomatic];                 // If the textfield has been added as a subview to the cell,        // then make it the first responder and show the keyboard.        if (_isEditingEvent) {            [_txtEvent becomeFirstResponder];        }    }    }

Page 39: Google calendar integration in iOS app

www.letsnurture.com

Step 3Now let's update the tableView:cellForRowAtIndexPath: so it reflects the state of the first section at any given time:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{    ...    ...    ...    if ([indexPath section] == 0) {        if (!_isEditingEvent) {            // If currently the event description is not being edited then just show            // the value of the strEvent string and let the cell contain a disclosure indicator accessory view.            // Also, set the gray as the selection style.            [[cell textLabel] setText:_strEvent];            [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];            [cell setSelectionStyle:UITableViewCellSelectionStyleGray];        }        else{            // If the event description is being edited, then empty the textLabel text so as to avoid            // having text behind the textfield.            // Add the textfield as a subview to the cell's content view and turn the selection style to none.            [[cell textLabel] setText:@""];            [[cell contentView] addSubview:_txtEvent];            [cell setSelectionStyle:UITableViewCellSelectionStyleNone];        }    }}

Page 40: Google calendar integration in iOS app

www.letsnurture.com

Great! If you run the app now, you'll notice that the textfield appears on the table view when you tap on the row of the first section. However, you cannot make the textfield vanish and keep the edited value. Why? Because we need to implement the related IBAction methods of the input accessory view bar button items.

Step 4Let's begin with the acceptEditingEvent: IBAction method. In short, in this method we'll keep the typed event description on the strEvent string, we'll change the isEditingEvent flag's value, we'll make the keyboard disappear, and we'll refresh the table view.

Page 41: Google calendar integration in iOS app

www.letsnurture.com

- (IBAction)acceptEditingEvent:(id)sender {    // If the strEvent property is already initialized then set its value to nil    // as it's going to be re-allocated right after.    if (_strEvent) {        _strEvent = nil;    }         // Keep the text entered in the textfield.    _strEvent = [[NSString alloc] initWithString:[_txtEvent text]];     // Indicate that no longer the event description is being edited.    _isEditingEvent = NO;         // Resign the first responder and make the textfield nil.    [_txtEvent resignFirstResponder];    [_txtEvent removeFromSuperview];    _txtEvent = nil;     // Reload the row of the first section of the table view.    [_tblPostData reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]]                        withRowAnimation:UITableViewRowAnimationAutomatic];}

Page 42: Google calendar integration in iOS app

www.letsnurture.com

The cancelEditingEvent: is similar.

- (IBAction)cancelEditingEvent:(id)sender {    // Indicate that no longer the event description is being edited.    _isEditingEvent = NO;         // Resign the first responder.    [_txtEvent resignFirstResponder];    [_txtEvent removeFromSuperview];    _txtEvent = nil;         // Reload the first row of the first section of the table view.    [_tblPostData reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]]                        withRowAnimation:UITableViewRowAnimationAutomatic];}

Page 43: Google calendar integration in iOS app

www.letsnurture.com

Step 5In order to be perfectly complete regarding the textfield and the event description editing in general, we have one more thing left to do. Namely, we must handle the Return button of the keyboard and make it work just like the acceptEditingEvent: IBAction method. 

For this reason, implement the following delegate method:

-(BOOL)textFieldShouldReturn:(UITextField *)textField{    // In case the Return button on the keyboard is tapped, call the acceptEditingEvent: method    // to handle it.    [self acceptEditingEvent:nil];    return YES;}

As you can see, we simply make a call to the IBAction method and nothing more. Now, we are 100% complete regarding the event editing and the textfield manipulation.

Page 44: Google calendar integration in iOS app

www.letsnurture.com

8. Picking an Event Date

Step 1One part of our demo app is complete. Let's go ahead now and let's fully implement the date picking feature. 

In this case, what we want is when we tap on the row of the second section on the table view, to show the view that contains the date picker and through it to select a date. 

After that, we want the picked date to be displayed on the table view as well. Special care should be given to the fact that an event can be set for a specific time, but it can also be an all-day event, which means that picking a time has no point at all. We'll see all this next.

Page 45: Google calendar integration in iOS app

www.letsnurture.com

Let's begin by showing the date picker container view to the self.view. It's just a matter of one line, which should be written in the tableView:didSelectRowAtIndexPath: delegate method, under any other content it has until now:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{    ...    ...    else if ([indexPath section] == 1){        // If the row of the second section is tapped, just show the view that contains the date picker.        [self.view addSubview:_viewDatePicker];    }}

Page 46: Google calendar integration in iOS app

www.letsnurture.com

Step 2Okay, that was the easy part. If you run the app now and you tap on the row of the second section, the date picker container view will be displayed on the screen. 

You'll notice that by default, both date and time are represented in the picker. 

That's nice if we want to set a specific time for the event. However, we should not let the time appear on the date picker if we are talking about an all-day event. Therefore, we need to implement the toggleDatePicker: IBAction method.

The way this method is going to work is fairly simple. Depending on the current date picker's contents, we will set its mode and we'll also change the respective bar button item's title. 

Don't forget that there is a flag as well, the isFullDayEvent variable, that should be changed accordingly. The following is the implementation:

Page 47: Google calendar integration in iOS app

www.letsnurture.com

- (IBAction)toggleDatePicker:(id)sender {    if ([_dpDatePicker datePickerMode] == UIDatePickerModeDateAndTime) {        // If the date picker currently shows both date and time, then set it to show only date        // and change the title of the barItemToggleDatePicker item.        // In this case the user selects to make a full-day event.        [_dpDatePicker setDatePickerMode:UIDatePickerModeDate];        [_barItemToggleDatePicker setTitle:@"Specific time"];    }    else{        // Otherwise, if only date is shown on the date picker, set it to show time too.        // The event is no longer a full-day one.        [_dpDatePicker setDatePickerMode:UIDatePickerModeDateAndTime];        [_barItemToggleDatePicker setTitle:@"All-day event"];    }         // Change the flag that indicates whether is a full-day event or not.    _isFullDayEvent = !_isFullDayEvent;}

Page 48: Google calendar integration in iOS app

www.letsnurture.com

Give it another try now and tap (or click on the Simulator) on the All-day event bar button item. Notice how the contents of the date picker get changed, along with the title of the button.

Step 3Now we know when an event is set as a full-day event, but we are still unable to keep the selected date and to make it appear on the table view. Similarly, we cannot yet cancel the date picking and go back to our view.

So, let's work on both of these IBAction methods now.

In the acceptSelectedDate: IBAction method we need to do only four things: (1) keep the selected date as a string, (2) store the date as a NSDate object, (3) remove the view from the superview, and, finally, (4) reload our table view in order to show the selected date.

Page 49: Google calendar integration in iOS app

www.letsnurture.com

- (IBAction)acceptSelectedDate:(id)sender { // Keep the selected date as a NSDate object. _dtEvent = [_dpDatePicker date]; // Also, convert it to a string properly formatted depending on whether the event is a full-day one or not // by calling the getStringFromDate: method. _strEventDate = [[NSString alloc] initWithString:[self getStringFromDate:[_dpDatePicker date]]]; // Remove the view with the date picker from the self.view. [_viewDatePicker removeFromSuperview]; // Reload the row of the second section of the table view to reflect the selected date. [_tblPostData reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:1]] withRowAnimation:UITableViewRowAnimationAutomatic];}

Page 50: Google calendar integration in iOS app

www.letsnurture.com

In the cancelPickingDate: IBAction method, we only need to remove the date picker container view from the superview.

- (IBAction)cancelPickingDate:(id)sender { // Just remove the view with the date picker from the superview. [_viewDatePicker removeFromSuperview];}

Page 51: Google calendar integration in iOS app

www.letsnurture.com

Step 4In the acceptSelectedDate: method, we made a call to the getStringFromDate: private method, which is declared but not yet implemented. It's now time to work with this method. Before I present the code, I should make an observation.

The purpose of the getStringFromDate: method is to get the date we provide (the selected date in our example) and to return this date as a string and formatted the way we want. However, there are two kind of string formats we need to have, depending on whether the event is a full-day one or not. If the event date has a specific time, we want this time to be present on the string. This means that we'll have a condition in our method that will determine what the output string format will be. So, having made our intention clear, enter the following code:

Page 52: Google calendar integration in iOS app

www.letsnurture.com

-(NSString *)getStringFromDate:(NSDate *)date{ // Create a NSDateFormatter object to handle the date. NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; if (!_isFullDayEvent) { // If it's not a full-day event, then set the date format in a way that contains the time too. [formatter setDateFormat:@"EEE, MMM dd, yyyy, HH:mm"]; } else{ // Otherwise keep just the date. [formatter setDateFormat:@"EEE, MMM dd, yyyy"]; } // Return the formatted date as a string value. return [formatter stringFromDate:date];}

Page 53: Google calendar integration in iOS app

www.letsnurture.com

The above will give us something like Mon, Aug 12, 2013, 17:32.

For more information about the date symbols used here and any other symbols that exist, look at the Date Format Patterns.

Note: Keep in mind that you should change the date symbol order in a real app in order to match the date representation of your own country.

Page 54: Google calendar integration in iOS app

www.letsnurture.com

Step 5So far so good: just one thing left to do. Add some code on the tableView:cellForRowAtIndexPath: method so the selected date will be displayed. Under all of the other contents of the method, add the next snippet:-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ ... ... ... else if ([indexPath section] == 1){ // In the event date cell just show the strEventDate string which either prompts the user // to pick a date, or contains the selected date as a string. // Also, add a disclosure indicator view. [[cell textLabel] setText:_strEventDate]; [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; } return cell;}

Page 55: Google calendar integration in iOS app

www.letsnurture.com

9. App Authorization

If you have already run the app, or if you do it now, you'll notice that the row of the third section on the table view contains the Download calendars... message.

Of course, nothing takes place when you tap on this method.

What we'd like to do on tap is to make an API call to Google and request the information we need. But, prior to this, we must authorize ourselves against the

Google service and obtain an access token that will be used to exchange data.

Actually, all of this will be done by the GoogleOAuth class we included early on.

All wee need to do is provide this class with the client ID, the client secret, and the scope. So, let's pay a visit to the Google developers website and get all the values we need.

Page 56: Google calendar integration in iOS app

www.letsnurture.com

Step 1Go to the Google Developer website. Click on the Sign In button that exists on the top-right side of the webpage to login.

Page 57: Google calendar integration in iOS app

www.letsnurture.com

After you have signed in, scroll down on the page until you locate the API Console icon.

Click on it and you'll be transferred to your Dashboard, where you handle all of your projects.

If you must, create a project now, otherwise select the project you created from the previous tutorial in this series. On the menu at the left side of the webpage, click on the API Access option.

Page 58: Google calendar integration in iOS app

www.letsnurture.com

Details about the current project will be displayed on the right side of the page.

In there, you can track down the client ID and client secret values that you will need. Note them, and let's move ahead.

Page 59: Google calendar integration in iOS app

www.letsnurture.com

Next, we need to tell Google that we want to use the Calendars service. To do so, click on the Services option at the menu on the left side of the webpage.

A list of all the provided services will appear. Locate the Calendar API item. Click on the Off button to enable the specific service for the current project.

Page 60: Google calendar integration in iOS app

www.letsnurture.com

Step 2

What we haven't located yet is the scope value for getting the calendar info we need. Just to remind you, a scope indicates an API that the app requests access for.

The best practice to locate what you want is to use the search engine for the Google developer website. So, go to the homepage of the Google developer site and search for the term Google Calendar API. In the results page, click on the first result.

ake a look around if you want and explore using the menus. For this tutorial, you should go to Reference > Calendar List > list.

A new webpage is loaded, containing information about the calendar list API call.

Find the Authorization area near the bottom of the page. There you can find the scope we need: https://www.googleapis.com/auth/calendar.

Page 61: Google calendar integration in iOS app

www.letsnurture.com

Step 3

In the previous steps, I showed you how you can enable a service on Google and the best way to find what you need from the developer web site.

Now, we can keep building the app.

Now that we have access to all the data we need from Google, let's get back to our app and see how to use the information.

Append the following code to our project:

Page 62: Google calendar integration in iOS app

www.letsnurture.com

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ ... ... ... else if ([indexPath section] == 2){ if (_arrGoogleCalendars == nil || [_arrGoogleCalendars count] == 0) { // If the arrGoogleCalendars array is nil or contains nothing, then the calendars should be // downloaded from Google. // So, show the activity indicator view and authorize the user by calling the the next // method of our custom-made class. [self showOrHideActivityIndicatorView]; [_googleOAuth authorizeUserWithClienID:@"YOUR_CLIENT_ID" andClientSecret:@"YOUR_CLIENT_SECRET" andParentView:self.view andScopes:[NSArray arrayWithObject:@"https://www.googleapis.com/auth/calendar"]]; }}

Page 63: Google calendar integration in iOS app

www.letsnurture.com

You'll notice that above we display the indicator view as well.

We do this because we don't know how long it'll take to obtain authorization. Don't forget to set your own values for the client ID and the client secret!

When you use the app for the first time, the embedded web view will appear.

You must enter your credentials and sign into your Google account to allow the app to access your calendars. If everything goes okay, you'll be authorized without a problem.

Page 64: Google calendar integration in iOS app

www.letsnurture.com

10. Downloading Calendar Data

Step 1At this point, we need to implement some of the GoogleOAuth delegate methods.

Let's begin with the authorizationWasSuccessful method, where we'll handle a successful authorization by making the API call for getting the calendar list.

However, we need the API URL string if we want to proceed. Navigate to the proper calendar list page in your Google developer account. At the top of the page you'll find the URL along with the HTTP method that should be used.

Page 65: Google calendar integration in iOS app

www.letsnurture.com

Now we can implement the delegate method:

-(void)authorizationWasSuccessful{ // If user authorization is successful, then make an API call to get the calendar list. // For more infomation about this API call, visit: // https://developers.google.com/google-apps/calendar/v3/reference/calendarList/list [_googleOAuth callAPI:@"https://www.googleapis.com/calendar/v3/users/me/calendarList" withHttpMethod:httpMethod_GET postParameterNames:nil postParameterValues:nil];}

Page 66: Google calendar integration in iOS app

www.letsnurture.com

Step 2If all works according to plan, the responseFromServiceWasReceived:andResponseJSONAsData: delegate method will be called by the GoogleOAuth class.

We are responsible to check if Google responded with the desired results, and then to keep only the data that we care about.

Let's discuss a bit about what the response contains and how we are going to manage the data.

What we should do first is to convert the response JSON data into an NSDictionary object. If you NSLog this dictionary, we'll see the way the returned data is formed. See the following example:

Page 67: Google calendar integration in iOS app

www.letsnurture.com

{etag = "\"AaJWGrGt8CrZSonQa3iAA4QAo_s/oZDiRXBvAIXr3JkNwKQRZZfQzQ4\""; items = ( { … } { … } { … } ); kind = "calendar#calendarList";}

Page 68: Google calendar integration in iOS app

www.letsnurture.com

Inside each curly bracket there is a block containing a bunch of information regarding every calendar you have created in Google Calendars.

The items object is equivalent to an array which contains dictionaries as objects.

In other words, we will extract the items object as a NSArray and we'll handle every single object of it as a NSDictionary object.

Page 69: Google calendar integration in iOS app

www.letsnurture.com

Let's get back on track again. Once we acquire all the items as NSArray objects, we'll go through a loop to access each calendar's details and we'll keep only the values we want for the purposes of this example.

Actually, we are going to create key-value pairs with these values with the goal of creating new NSDictionaries, which will be stored in the arrGoogleCalendars array. This array is the calendar list for our app.

Also, the dictCurrentCalendar dictionary will be initialized with the contents of the first calendar from the list. Once this has been done, the Post and Logout items will become enabled. We'll also hide the activity indicator view and we'll refresh the table to show the selected calendar.

Page 70: Google calendar integration in iOS app

www.letsnurture.com

-(void)responseFromServiceWasReceived:(NSString *)responseJSONAsString andResponseJSONAsData:(NSData *)responseJSONAsData{ NSError *error; if ([responseJSONAsString rangeOfString:@"calendarList"].location != NSNotFound) { // If the response from Google contains the "calendarList" literal, then the calendar list // has been downloaded. // Get the JSON data as a dictionary. NSDictionary *calendarInfoDict = [NSJSONSerialization JSONObjectWithData:responseJSONAsData options:NSJSONReadingMutableContainers error:&error]; if (error) { // This is the case that an error occured during converting JSON data to dictionary. // Simply log the error description. NSLog(@"%@", [error localizedDescription]); }

Page 71: Google calendar integration in iOS app

www.letsnurture.com

else{ // Get the calendars info as an array. NSArray *calendarsInfo = [calendarInfoDict objectForKey:@"items"]; // If the arrGoogleCalendars array is nil then initialize it so to store each calendar as a NSDictionary object. if (_arrGoogleCalendars == nil) { _arrGoogleCalendars = [[NSMutableArray alloc] init]; }

Page 72: Google calendar integration in iOS app

www.letsnurture.com

// Make a loop and get the next data of each calendar. for (int i=0; i<[calendarsInfo count]; i++) { // Store each calendar in a temporary dictionary. NSDictionary *currentCalDict = [calendarsInfo objectAtIndex:i]; // Create an array which contains only the desired data. NSArray *values = [NSArray arrayWithObjects:[currentCalDict objectForKey:@"id"], [currentCalDict objectForKey:@"summary"], nil]; // Create an array with keys regarding the values on the previous array. NSArray *keys = [NSArray arrayWithObjects:@"id", @"summary", nil]; // Add key-value pairs in a dictionary and then add this dictionary into the arrGoogleCalendars array. [_arrGoogleCalendars addObject: [[NSMutableDictionary alloc] initWithObjects:values forKeys:keys]]; }

Page 73: Google calendar integration in iOS app

www.letsnurture.com

// Set the first calendar as the selected one. _dictCurrentCalendar = [[NSDictionary alloc] initWithDictionary:[_arrGoogleCalendars objectAtIndex:0]]; // Enable the post and the sign out bar button items. [_barItemPost setEnabled:YES]; [_barItemRevokeAccess setEnabled:YES]; // Stop the activity indicator view. [self showOrHideActivityIndicatorView]; // Reload the table view section. [_tblPostData reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:2]] withRowAnimation:UITableViewRowAnimationAutomatic]; } }}

Page 74: Google calendar integration in iOS app

www.letsnurture.com

Step 3

Now that we've done all the above, we want to be able to tap on a calendar name and have the full list expand, allowing us to select another calendar.

This will be done in the tableView:didSelectRowAtIndexPath: method. Add the following code snippet:

Page 75: Google calendar integration in iOS app

www.letsnurture.com

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ ...else{ // In this case the calendars exist in the arrGoogleCalendars array. if (_isCalendarListExpanded) { // If the calendar list is shown on the table view, then the tapped one shoule become the selected calendar. // Re-initialize the dictCurrentCalendar dictionary so it contains the information regarding the selected one. _dictCurrentCalendar = nil; _dictCurrentCalendar = [[NSDictionary alloc] initWithDictionary:[_arrGoogleCalendars objectAtIndex:[indexPath row]]]; } // Change the value of the isCalendarListExpanded which indicates whether only the selected calendar is shown, or the // whole list. _isCalendarListExpanded = !_isCalendarListExpanded; // Finally, reload the section. [_tblPostData reloadSections:[NSIndexSet indexSetWithIndex:2] withRowAnimation:UITableViewRowAnimationAutomatic]; } } }

Page 76: Google calendar integration in iOS app

www.letsnurture.com

Step 4Finally, we need to update the tableView:cellForRowAtIndexPath: method to display everything we've done. Append the following code:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ ... ... ... else if ([indexPath section] == 2){ // This is the case where either the selected calendar is shown, or a list with all of them. if (!_isCalendarListExpanded) { // If the calendar list is not expanded and only the selected calendar is shown, // then if the arrGoogleCalendars array is nil or it doesn't have any contents at all prompt // the user to download them now. // Otherwise show the summary (title) of the selected calendar along with a disclosure indicator. if (![_arrGoogleCalendars count] || [_arrGoogleCalendars count] == 0) { [[cell textLabel] setText:@"Download calendars..."]; }

Page 77: Google calendar integration in iOS app

www.letsnurture.com

else{ [[cell textLabel] setText:[_dictCurrentCalendar objectForKey:@"summary"]]; }[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; }else{ // This is the case where all the calendars should be listed.// Note that each calendar is represented as a NSDictionary which is read from the // arrGoogleCalendars array. // If the calendar that is shown in the current cell is the already selected one, // then add the checkmark accessory type to the cell, otherwise set the accessory type to none. NSDictionary *tempDict = [_arrGoogleCalendars objectAtIndex:[indexPath row]]; [[cell textLabel] setText:[tempDict objectForKey:@"summary"]]; if ([tempDict isEqual:_dictCurrentCalendar]) { [cell setAccessoryType:UITableViewCellAccessoryCheckmark]; } else{ [cell setAccessoryType:UITableViewCellAccessoryNone]; } } } return cell; }

Page 78: Google calendar integration in iOS app

www.letsnurture.com

That's it. Go and give it a try. Watch your calendars on the Simulator and play around for a while by expanding the calendar list and selecting a calendar!

11. Posting Calendar Events

Step 1Let's see how we'll manage to add an event to a selected calendar. The first thing we should do is make sure that the event description and the event date have been set. To verify this, we'll check their values and we'll show an alert if something is wrong.

Our work will now take place in the post: IBAction method.

Page 79: Google calendar integration in iOS app

www.letsnurture.com

- (IBAction)post:(id)sender { // Before posting the event, check if the event description is empty or a date has not been selected. if ([_strEvent isEqualToString:@""]) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"Please enter an event description." delegate:self cancelButtonTitle:nil otherButtonTitles:@"Okay", nil]; [alert show]; return; } if ([_strEventDate isEqualToString:@"Pick a date..."]) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"Please select a date for the event." delegate:self cancelButtonTitle:nil otherButtonTitles:@"Okay", nil]; [alert show]; return; } ...}

Page 80: Google calendar integration in iOS app

www.letsnurture.com

You'll notice that we'll simply check if the event description string is equal to the empty string and if the event date string is equal to its initial value.

Step 2

As I have already said, what we actually do in this project is to implement the Quick-add feature that Google Calendar supports.

However, we need to know the format for the event string because there are some rules that apply.

For example, there are special ways that the event date and time should be appended at the end of the event description string, so Google will know the exact date/time of the event.

Of course, if you have already used the online Quick-Add feature, then you surely know what I am talking about.

Page 81: Google calendar integration in iOS app

www.letsnurture.com

Thankfully, Google provides help and examples regarding this issue. We just have to visit the Quick Add documentation. Go and visit this website and familiarize your self with this feature.

In our case, if we have a full-day event, we simply have to add the date using slashes at the end of the event description string (for example, "This is an event 08/12/2013"). If we don't have a full-day event, then we will add the time too, using the "at" between the date and time (for example, "This is an event 08/12/2013 at 21:40").

In addition, we need to know the URL of the API we want to call. Just like we with the calendar list, we must find the quick-add related information in the Google Calendar API documentation. If you don't want to bother looking for it right now, this is where you can find it. We must search for the following information:

Page 82: Google calendar integration in iOS app

www.letsnurture.com

Request: This is the URL of the API we want to call as it appeared at the top of the page.

Also notice that we need to use the POST HTTP method.POST parameters:

Here are the parameters we need to send with the POST method. There are only two mandatory params, the ID of the calendar on which we want to add the event and the event text (of course formatted with the date, as I indicated before).

Authorization: This is the scope that we should be authorizing. In this case, the scope is equal to the calendar list scope, so we don't need to care about it. However, if that was a different value, then we should include it in the scope array during authorization.

Page 83: Google calendar integration in iOS app

www.letsnurture.com

- (IBAction)post:(id)sender { ... ... ... // Create the URL string of API needed to quick-add the event into the Google calendar. // Note that we specify the id of the selected calendar. NSString *apiURLString = [NSString stringWithFormat:@"https://www.googleapis.com/calendar/v3/calendars/%@/events/quickAdd", [_dictCurrentCalendar objectForKey:@"id"]]; // Build the event text string, composed by the event description and the date (and time) that should happen. // Break the selected date into its components. NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; dateComponents = [[NSCalendar currentCalendar] components:NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:_dtEvent];

Page 84: Google calendar integration in iOS app

www.letsnurture.com

if (_isFullDayEvent) { // If a full-day event was selected (meaning without specific time), then add at the end of the string just the date. _strEventTextToPost = [NSString stringWithFormat:@"%@ %d/%d/%d", _strEvent, [dateComponents month], [dateComponents day], [dateComponents year]]; } else{ // Otherwise, append both the date and the time that the event should happen. _strEventTextToPost = [NSString stringWithFormat:@"%@ %d/%d/%d at %d.%d", _strEvent, [dateComponents month], [dateComponents day], [dateComponents year], [dateComponents hour], [dateComponents minute]]; }

Page 85: Google calendar integration in iOS app

www.letsnurture.com

// Show the activity indicator view. [self showOrHideActivityIndicatorView]; // Call the API and post the event on the selected Google calendar.

// Visit https://developers.google.com/google-apps/calendar/v3/reference/events/quickAdd for more information about the quick-add event API call. [_googleOAuth callAPI:apiURLString withHttpMethod:httpMethod_POST postParameterNames:[NSArray arrayWithObjects:@"calendarId", @"text", nil] postParameterValues:[NSArray arrayWithObjects:[_dictCurrentCalendar objectForKey:@"id"], _strEventTextToPost, nil]];}

Page 86: Google calendar integration in iOS app

www.letsnurture.com

If you run the app now and you click on the Post button, the event will be posted. You can verify this if you check your calendar from a web browser. However, until we handle the response from Google, we are unable to know if the event was successfully added or not.

Step 3Each time that an event is posted, Google creates a respective object which contains several properties and data.

After a successful addition, Google responds with this data, so we can have any information we need regarding the newly created event. In our case, we won't do something extraordinary. We'll simply show an alert view that will contain the following values, so we are sure that the event was successfully posted.

Page 87: Google calendar integration in iOS app

www.letsnurture.com

ID: Each new event gets a unique ID value, which we are going to display on the alert view.Created Date: The date that the event was created.Summary: The event description itself.

Of course, in a real app, you must handle this event data in a different way. Always regard the app's needs.

We are going to work in the responseFromServiceWasReceived:andResponseJSONAsData: method again. Notice that the JSON data is converted again into an NSDictionary object.

Page 88: Google calendar integration in iOS app

www.letsnurture.com

-(void)responseFromServiceWasReceived:(NSString *)responseJSONAsString andResponseJSONAsData:(NSData *)responseJSONAsData{ NSError *error; ... ... ... else if ([responseJSONAsString rangeOfString:@"calendar#event"].location != NSNotFound){ // If the Google response contains the "calendar#event" literal then the event has been added to the selected calendar // and Google returns data related to the new event. // Get the response JSON as a dictionary. NSDictionary *eventInfoDict = [NSJSONSerialization JSONObjectWithData:responseJSONAsData options:NSJSONReadingMutableContainers error:&error]; if (error) { // This is the case that an error occured during converting JSON data to dictionary. // Simply log the error description. NSLog(@"%@", [error localizedDescription]); return; }

Page 89: Google calendar integration in iOS app

www.letsnurture.com

// An alert view with some information regarding the just added event will be shown. // Keep only the information that will be shown to the alert view. // Look at the https://developers.google.com/google-apps/calendar/v3/reference/events#resource for a complete list of the // data fields that Google returns. NSString *eventID = [eventInfoDict objectForKey:@"id"]; NSString *created = [eventInfoDict objectForKey:@"created"]; NSString *summary = [eventInfoDict objectForKey:@"summary"];// Build the alert message. NSString *alertMessage = [NSString stringWithFormat:@"ID: %@\n\nCreated:%@\n\nSummary:%@", eventID, created, summary]; // Stop the activity indicator view. [self showOrHideActivityIndicatorView];// Show the alert view. UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"New event" message:alertMessage delegate:self cancelButtonTitle:nil otherButtonTitles:@"Great", nil]; [alert show]; }}

Page 90: Google calendar integration in iOS app

www.letsnurture.com

Now, every time you add an event an alert view containing the new event info is displayed.

12. Signing Out

Signing out of the Google account is an option that should always be provided to the users, even though it's recommended to keep them connected for faster access to online services.

For our app, it's only a matter of one single line of code, which we'll add on the revokeAccess: IBAction method.

Page 91: Google calendar integration in iOS app

www.letsnurture.com

13. Ancillary Methods

Step 1Until now, we used only two delegate methods of the GoogleOAuth class, the authorizationWasSuccessful and the responseFromServiceWasReceived:andResponseJSONAsData:.

There are three more of them that we should implement. We need a delegate method for handling the access revocation, another delegate for handling any error that may occur, and a final method for dealing with any error messages that may exist in Google responses.

Regarding the access revocation, we'll have to do only three things. First, we need to remove all calendars from the arrGoogleCalendars array. Next, we need to disable the Post and the Sign Out buttons. Finally, we need to reload the table view to keep it up to date.

Page 92: Google calendar integration in iOS app

www.letsnurture.com

-(void)accessTokenWasRevoked{ // Remove all calendars from the array. [_arrGoogleCalendars removeAllObjects]; _arrGoogleCalendars = nil; // Disable the post and sign out bar button items. [_barItemPost setEnabled:NO]; [_barItemRevokeAccess setEnabled:NO]; // Reload the Google calendars section. [_tblPostData reloadSections:[NSIndexSet indexSetWithIndex:2] withRowAnimation:UITableViewRowAnimationAutomatic];}

Page 93: Google calendar integration in iOS app

www.letsnurture.com

For the next two error handling delegate methods, we won't do much. We'll simply log the error messages and nothing further.

It's obvious that in a real app you would have to handle the errors in an appropriate way and figure out workarounds that handle unexpected situations. For now, here are our stub implementations:

-(void)errorOccuredWithShortDescription:(NSString *)errorShortDescription andErrorDetails:(NSString *)errorDetails{ // Just log the error messages. NSLog(@"%@", errorShortDescription); NSLog(@"%@", errorDetails);} -(void)errorInResponseWithBody:(NSString *)errorMessage{ // Just log the error message. NSLog(@"%@", errorMessage);}

Page 94: Google calendar integration in iOS app

www.letsnurture.com

Step 2During the project implementation, we made a few calls to the showOrHideActivityIndicatorView private method, which has been declared and called but not yet built. Let's deal with it now.

-(void)showOrHideActivityIndicatorView{ // If the activity indicator view is not currently animating (spinning), // then set its view center equal to self view's center, add it as a subview and start animating. // Otherwise stop animating and remove it from the superview. if (![_activityIndicatorView isAnimating]) { [_activityIndicatorView setCenter:self.view.center]; [self.view addSubview:_activityIndicatorView]; [_activityIndicatorView startAnimating]; } else{ [_activityIndicatorView stopAnimating]; [_activityIndicatorView removeFromSuperview]; } }

Page 95: Google calendar integration in iOS app

Follow us on https://www.facebook.com/LetsNurture

https://twitter.com/letsnurture

http://www.linkedin.com/company/letsnurture

[email protected]

www.letsnurture.com | www.letsnurture.co.uk