Tuesday, December 25, 2012

How To Add Search Bar in Table View

http://www.appcoda.com/how-to-add-search-bar-uitableview/

One common questions I got about UITableView is how to implement a search bar for data searching. This tutorial will show how to add a search bar to the Tab Bar project. With the search bar, the app lets users search through the recipe list by specifying a search term.
Well, it’s not difficult to add a search bar but it takes a little bit of extra work. We’ll continue to work on the Xcode project we developed in the previous tutorial. If you haven’t gone through the tutorial, take some time to check it out or you can download the project here.
iOS App Search Bar

Understanding Search Display Controller

You can use search display controller (i.e. UISearchDisplayController class) to manage search in your app. A search display controller manages display of a search bar and a table view that displays the results of a search of data.
When a user starts a search, the search display controller will superimpose the search interface over the original view and display the search results. Interestingly, the results are displayed in a table view that’s created by the search display controller.
Search Results Table View vs Table View
Search Results Table View vs Table View
Like other view controllers, you can either programmatically create the search display controller or simply add it into your app using Storyboard. In this tutorial, we’ll use the later approach.

Adding a Search Display Controller in Storyboard

In Storyboard, drag and add the “Search Bar and Search Display Controller” right below the navigation bar of Recipe Book View Controller. If you’ve done correctly, you should have a screen similar to the below:
Adding Search Display Controller
Adding Search Display Controller
Before proceeding, try to run the app and see how it looks. Without implementing any new code, you already have a search bar. Tapping the search bar will bring you to the search interface. Yet, the search won’t give you the correct search result.
Search Bar in Table View App
Search Bar in Table View App But Not Working Yet

We Did Nothing but Why Search Results Show All Recipes?

As mentioned earlier, the search results are displayed in a table view created by the search display controller. When developing the table view app, we implement the UITableViewDataSource protocol to tell Table View how many rows to display and the data in each row.
Like UITableView, the table view created by the search display controller adopts the same approach. By referring to the official documentation of UISearchDisplayController, here are the available delegates that let you interact with the search result and search bar:
The search results table view’s data source.
This object is responsible for providing the data for the results table.
The search results table view’s delegate.
This object is responsible for, amongst other things, responding to the user’s selection of an item in the results table.
The search display controller’s delegate.
The delegate conforms to the UISearchDisplayDelegate protocol. It is notified of events such as when the search starts or ends, and when the search interface is displayed or hidden. As a convenience, it may also be told about changes to the search string or search scope, so that the results table view can be reloaded.
The search bar’s delegate.
This object is responsible for responding to changes in the search criteria.
Typically, the original view controller is used as the source object for the search results data source and delegate. You do not need to manually link up the data source and delegate with the view controller. As you insert the search bar into the view of Recipe Book View Controller, the appropriate connections to the search display controller are automatically configured. You can press the “control” key and click on the “Search Display Controller” to reveal the connections.
Search Display Controller Connections
Search Display Controller Connections
Both table views (i.e. the table view in Recipe Book View Controller and the search result table view) shares the same view controller to handle data population. If you refer to the code, these are the two methods being invoked when displaying table data:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [recipes count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *simpleTableIdentifier = @"RecipeCell";
   
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
   
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
    }
   
    cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
    return cell;
}
This explains why the search results show a full list of recipes regardless of your search term.

Implementing Search Filter

Obviously, to make the search works, there are a couple of things we have to implement/change:
  1. Implement methods to filter the recipe names and return the correct search results
  2. Change the data source methods to differentiate the table views. If the tableView being passed is the table view of Recipe Book View Controller, we show all recipes. On the other hand, if it’s a search result table view, only the search results are displayed.
First, we’ll show you how to implement the filter. Here we have an array to store all recipes. We create another array to store the search results. Let’s name it as “searchResults”.
1
2
3
4
@implementation RecipeBookViewController {
    NSArray *recipes;
    NSArray *searchResults;
}
Next, add a new method to handle the search filtering. Filtering is one of the common tasks in iOS app. The straightforward way to filter the list of recipes is to loop through all the names and filter the result with the if-statement. There is nothing wrong with such implementation. But iOS SDK offers a better way known as Predicate to handle search queries. By using NSPredicate (which is an object representation of a predicate), you write less code. With just two lines of code, it searches through all recipes and returns the matched results.
1
2
3
4
5
6
7
8
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
    NSPredicate *resultPredicate = [NSPredicate
                                    predicateWithFormat:@"SELF contains[cd] %@",
                                    searchText];
   
    searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];
}
Basically, a predicate is an expression that returns a Boolean value (true or false). You specify the search criteria in the format of NSPredicate and use it to filter data in the array. NSArray provides filteredArrayUsingPredicate: method which returns a new array containing objects that match the specified predicate. The SELF keyword in the predicate “SELF contains[cd] %@” refers to the objects being evaluated (i.e. recipes). The operator “[cd]” means the comparison is case- and diacritic-insensitive.
If you want to learn more about Predicate, check out Apple’s official documentation or the tutorial written by Peter Friese.

Implementing Search Display Controller Delegate

Now we’ve created a method to handle the data filtering. But when should it be called? Apparently the filterContentForSearchText: method is invoked when user keys in the search term. The UISearchDisplayController class comes with a shouldReloadTableForSearchString: method which is automatically called every time the search string changes. So add the following method in the RecipeBookViewController.m:
1
2
3
4
5
6
7
8
9
10
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
    [self filterContentForSearchText:searchString
                               scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
                                      objectAtIndex:[self.searchDisplayController.searchBar
                                                     selectedScopeButtonIndex]]];
   
    return YES;
}

Display Search Results in searchResultsTableView

As explained earlier, we have to change the data source methods as to differentiate the table views (i.e. the table view in Recipe Book View Controller and the search result table view). It’s pretty easy to differentiate the table view. We simply compare the tableView object against the “searchResultsTableView” of the “searchDisplayController”. If the comparison is positive, we display the search results instead of all recipes. Here are the changes of the two methods:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (tableView == self.searchDisplayController.searchResultsTableView) {
        return [searchResults count];

    } else {
        return [recipes count];
       
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *simpleTableIdentifier = @"RecipeCell";
   
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
   
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
    }
   
    if (tableView == self.searchDisplayController.searchResultsTableView) {
        cell.textLabel.text = [searchResults objectAtIndex:indexPath.row];
    } else {
        cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
    }
   
    return cell;
}

Test the App Again

Once you complete the above changes, test your app again. Now the search bar should work properly!
Search Bar Complete

Handling Row Selection in Search Results

Despite the search works, it doesn’t respond to your row selection. We want to make it work like the recipe table view. When user taps on any of the search results, it’ll transit to the detail view displaying the name of selected recipe.
Earlier, we use Segue to link up the recipe table cell and detail view. (If you forgot how it was done, revisit the Segue tutorial to see how it works.)
Obviously, we have to create another Segue in Storyboard to define the transition between the search result and detail view. The problem is we can’t do that. The search result table view is a private variable of search display controller. It’s impossible to handle the row selection of the search results using Storyboard.
The search display table view, however, lets you interact with the user’s selection of the results table by using a delegate. When the user selects a row, the didSelectRowAtIndexPath: method will be called. Therefore, what we have to do is to implement the method:
1
2
3
4
5
6
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{  
    if (tableView == self.searchDisplayController.searchResultsTableView) {
        [self performSegueWithIdentifier: @"showRecipeDetail" sender: self];      
    }
}
We simply invoke the performSegueWithIdentifier: method to manually trigger the “showRecipeDetail” segue. Before proceeding, try to run the app again. When you select any of the search results, the app shows the detail view with a recipe name. But the name is not always correct.
Referring to the prepareForSegue: method, we use the “indexPathForSelectedRow” method to retrieve the indexPath of the selected row. As mentioned earlier, the search results are displayed in a separate table view. But in our original prepareForSegue: method, we always retrieve the selected row from the table view of Recipe Book View Controller. That’s why we got the wrong recipe name in detail view. To make the selection of search results properly, we have to tweak the prepareForSegue: method:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"showRecipeDetail"]) {
        RecipeDetailViewController *destViewController = segue.destinationViewController;
       
        NSIndexPath *indexPath = nil;

        if ([self.searchDisplayController isActive]) {
            indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
            destViewController.recipeName = [searchResults objectAtIndex:indexPath.row];
           
        } else {
            indexPath = [self.tableView indexPathForSelectedRow];
            destViewController.recipeName = [recipes objectAtIndex:indexPath.row];
        }
    }
   
}
We first determine if the user is using search. When searching, we retrieve the indexPath from searchResultsTableView, which is the table view for search results. Otherwise, we just get the indexPath from the table view of Recipe Book View Controller.
That’s it. Run the app again and the search selection should work as expected.
Search Results Selected

Tell Us What You Think

Hope you find this tutorial useful. If you like the tutorial and have any ideas about future tutorial, leave us comment and tell us what you think. We need your support to keep publishing free tutorials :-)

How To Handle Row Selection in UITableView

http://www.appcoda.com/how-to-handle-row-selection-in-uitableview/

If you’ve followed the iOS programming tutorials, I believe you should manage to create a simple Table View app with custom table cell. So far we focus on displaying data in the table view. But how do we know when someone taps on the table row? This is what we’ll cover in this post and show you how to handle row selection.
First, let’s revisit our app and see what we’ll add to it.
Simple Table App - Row Selection
There are a couple of changes we’ll try it out in this tutorial:
  • Display an alert message when user taps a row
  • Display a check mark when user selects a row

Understanding UITableViewDelegate

When you first built the Simple Table View app, you’ve declared two delegates (UITableViewDelegate, UITableViewDataSource) in the SimpleTableController.h:
1
2
3
4
5
#import <UIKit/UIKit.h>

@interface SimpleTableViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>

@end
As explained in the earlier tutorial, both delegates are known as protocol in Objective-C. You have to conform with the requirements defined in these protocols in order to build a UITableView.
It’s very common to come across various delegates in iOS programming. Each delegate is responsible for a specific role or task to keep the system simple and clean. Whenever an object needs to perform certain task, it depends on another object to handle it. This is usually known as separation of concern in system design.
When you look at the UITableView class, it also applies this design concept. The two delegates are catered for different purpose. The UITableViewDataSource delegate, that we’ve implemented, defines methods that are used for displaying table data. On the other hand, the UITableViewDelegate deals with the appearance of the UITableView, as well as, handles the row selection.
It’s obvious we’ll make use of the UITableViewDelegate and implement the required method for handling row selection.

Handling Table Row Selection

Before we change the code, you may wonder:
How do we know which methods in UITableViewDelegate need to implement?
You can always refer to the Apple’s iOS programming reference. There are two ways to access the documentation. You can access the API document on Apple’s website. Or simply look it up inside Xcode. For example, you can bring up the API document of UITableViewDelegate, just place the cursor over the class name and press “control-command-?”. You’ll see the following popup:
xcode api doc shortcut
Shortcut to Access API Doc
Click the UITableViewDelegate Protocol Reference to display the API document:
UITableViewDelegate Protocol Reference
UITableViewDelegate Protocol Reference
If you’ve read through the document, you’ll find these methods that are used for managing row selection:
– tableView:willSelectRowAtIndexPath:
– tableView:didSelectRowAtIndexPath:
Both of the methods are used for row selection. The only difference is that “willSelectRowAtIndexPath” is called when a specified row is about to be selected. Usually you make use of this method to prevent selection of a particular cell from taking place. Typically, you use “didSelectRowAtIndexPath” method, which is invoked after user selects a row, to handle the row selection and this is where you add code to specify the action when the row is selected. In this tutorial, we’ll add a couple of actions to handle row selection:
  • Display an alert message
  • Display a check mark to indicate the row is selected

Let’s Code

Okay, that’s enough for the explanation. Let’s move onto the interesting part – code, code, code!
In Xcode, open the “SimpleTableViewController.m” and add the following method before “@end”.
1
2
3
4
5
6
7
8
9
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UIAlertView *messageAlert = [[UIAlertView alloc]
                                    initWithTitle:@"Row Selected" message:@"You've selected a row" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
   
    // Display Alert Message
    [messageAlert show];
   
}
The code is very easy to understand. When a row is selected, the app creates an UIAlertView and shows an alert message. Try to run the app and this is what the app looks like when you tap a row:
SimpleTableApp Row Selected
When a row is selected, an alert message is displayed

Your Exercise

For now, we just display a generic message when a row is selected. It’s always better to display an informational message like below:
SimpleTableApp Row Selected Recipe
Think about how you can alter the code (hint: the indexPath parameter contains the row number of the selected row) and display the message like the screenshot shown above. It’s not difficult to do so if you’ve followed the previous tutorial.
Easy, right? With the use of delegate, it’s very straightforward to detect row selection. Next, we’ll add a few lines of code to display a tick for the selected item. Before that, let me take a look at the default content of a table cell:
UITableViewCell Structure
Default Structure of a UITableViewCell
A table cell can be broken into three parts:
  • Image – the left part is reserved for displaying thumbnail just like what we’ve done in the Simple Table App tutorial
  • Content – the main part is used for displaying text label and detailed text
  • Accessory view – the right part is reserved for accessory view. There are three types of default accessory view including disclosure indicator, detail disclosure button and check mark. The below figure shows you how these indicators look like.
TableCell Accessory View
UITableViewCell Accessory View
To display a check mark when a row is selected, you just need to add two lines of code after the “[messageAlert show]“:
1
2
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
The first line retrieves the selected table cell by using the indexPath. The second link updates the accessory view of the cell with a check mark.
Compile and run the app. After you tap a row, it’ll show you a check mark.
SimpleTableApp Check Mark
For now, when you select a row, that row will be highlighted in blue color. If you don’t like it, try to add the following code to deselect the row.
1
[tableView deselectRowAtIndexPath:indexPath animated:YES];

What’s Upcoming Next?

What do you think about the series of Table View tutorials? I hope you’ve learnt a ton! By now, you should have a better understanding about how to create table view, customize table cells and handle table row selection. Make sure you understand the information presented in the tutorials as UITableView is one of the common UI elements in iOS. If you have any questions, head to our forum and share with us.
There are still lots of stuffs to learn in iOS programming. In coming tutorials, we’ll see how you can replace the recipe array with a file and explore Navigation Controller, as well as, Storyboard to build a more complex application.

iOS Programming 101: Integrate Twitter and Facebook Sharing in Your App

http://www.appcoda.com/ios-programming-101-integrate-twitter-and-facebook-sharing-in-ios-6/

Following the Twitter support in iOS 5, Apple added the support of Facebook in iOS 6. In the past, developers have to make use of the Facebook and Twitter API to integrate the sharing feature in their apps. With the built-in support, it’s much easier to add these social features to your own app.
In this short tutorial, we will show you how to build Twitter and Facebook sharing feature in your app. As usual, we’ll build a simple app together as we believe there is no better way to teach programming than “get your hand dirty”.

Social Framework in iOS 6

The iOS 6 introduces a new framework known as the “Social Framework”. The Social framework lets you integrate your app with any supported social networking services. Presently, it supports Facebook, Twitter and Sina Weibo. The framework gives you a standard interface to interact with different social networks and it shields you from learning the internals. You don’t have to worry about the Twitter/Facebook APIs, how to handle network connection, handle single sign-on, etc. The social framework simplifies everything. You just need to write a few lines of code to bring up the composer and users can tweet / publish Facebook post within your app.

The framework comes with a very handy class named SLComposeViewController. The SLComposeViewController class presents a standard view controller for users to compose tweet or Facebook post. It also allows developers to preset the initial text, attach images and add URL to the post. If you just want to implement simple sharing feature, this is the only class you need to know and that we will go through today.
If you’re not familiar with the SLComposeViewController, this is what it looks like within your app.
User Interface for Twitter and Facebook in Your App
User Interface for Twitter and Facebook in Your App
Now you should have a basic idea about the framework. Let’s get started and build a simple app with Twitter and Facebook integration.

Create the Project and Design the Interface

As you need to use iOS 6 for this tutorial, please upgrade your Xcode to v4.5 or up before proceeding.
First, create a new Xcode project using the Single View Template. Let’s name the project as “SocialSharing” and set the project with the following parameters:
SocialSharing Xcode Project
SocialSharing Xcode Project
Once you’ve successfully created your project, go to the Storyboard and design the user interface. In the view, add two buttons. Name one as “Tweet” and the other one as “Facebook”.
SocialSharing App Interface Design
Designing the interface for the App

Establish the Connection Between Variables and UI Elements

Next, we’ll connect the UI elements with our code. In the Storyboard, select the view controller and switch to the Assistant Editor.
Show Assistant Editor
Show Assistant Editor and Hide Utility Area
Press and hold the control key, click the “Tweet” button and drag it towards the “SocialSharingViewController.h”. Create an action method and name it as “postToTwitter”. This method will be invoked when the button detects a Touch Up Inside event.
SocialSharing App Add Action Method
Add action methods for both Tweet and Facebook buttons
Repeat the same procedures the “Facebook” button and name the action method as “postToFacebook”. Below is the final code for “SocialSharingViewController.h”:
1
2
3
4
5
6
7
#import <UIKit/UIKit.h>

@interface SocialSharingViewController : UIViewController
- (IBAction)postToTwitter:(id)sender;
- (IBAction)postToFacebook:(id)sender;

@end

Adding Twitter Support

Let’s first start with the implementation of “postToTwitter” method. Open the “SocialSharingViewController.m” and add the following code for the “postToTwitter” method:
1
2
3
4
5
6
7
8
9
- (IBAction)postToTwitter:(id)sender {
    if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
    {
        SLComposeViewController *tweetSheet = [SLComposeViewController
                                               composeViewControllerForServiceType:SLServiceTypeTwitter];
        [tweetSheet setInitialText:@"Great fun to learn iOS programming at appcoda.com!"];
        [self presentViewController:tweetSheet animated:YES completion:nil];
    }
}
As “SLComposeViewController” is a class provided by the Social framework, remember to import the Social.h file at the very top of the “SocialSharingViewController.m”:
1
#import <Social/Social.h>
Before we move on, let’s take a look at the above code line by line.
Line #2 – Firstly, we use the “isAvailableForServiceType” method to verify if the Twitter service is accessible. One reason why users can’t access the Twitter service is that they haven’t logged on the service in the iOS.
Line #4 – If the service is accessible, we then create an instance of the SLComposeViewController for the Twitter service.
Line #5 – We set the initial text in the composer.
Line #6 – Finally, we invoke presentViewController:tweetSheet to bring up the Twitter composer.
That’s the code we need to let user tweet within your own app. It’s much easier than you thought, right? But we still miss one thing before the app can be run.
By default, the Social framework is not included in the Xcode project. To compile the app properly, add the “Social.framework” in the project. In the Project Navigator, select the “SocialSharing” project. In the Content Area, select “SocialSharing” under Targets and click “Build Phases”. Expand “Link Binary with Libraries” and click the “+” button to add the “Social.framework”.
SocialSharing Add Social Framework
Add Social framework to the project
Now, it’s ready to test the app. Click the “Run” button to try out the app in Simulator. When the app is launched, tap the “Tweet” button and you should see a similar screenshot as below:
SocialSharing Twitter App
Testing the Tweet Feature
In case you haven’t registered your Twitter account in the Simulator, you’ll end up with the below. Just go to Settings -> Twitter and sign on with your Twitter account.
SocialSharing Twitter Account Error
You haven’t registered your Twitter account in iOS

Adding Facebook Support

Next, we’ll implement the button for publishing wall post on Facebook. In the “SocialSharingViewController.m”, add the following code in the “postToFacebook” method:
1
2
3
4
5
6
7
8
- (IBAction)postToFacebook:(id)sender {
    if([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
            SLComposeViewController *controller = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
       
        [controller setInitialText:@"First post from my iPhone app"];
        [self presentViewController:controller animated:YES completion:Nil];      
    }
}
That’s it. The code is very similar to the code we’ve used in the “postToTwitter” method. The only change is the service type. Instead of using SLServiceTypeTwitter, we tell SLComposeViewController to use SLServiceTypeFacebook.
Let’s run the app again and click the “Facebook” button. Your app should bring up the composer for publishing Facebook post.
SocialSharing App Facebook Post

Adding Image and Link to Your Post

Wouldn’t be great to upload your post with image and link? The SLComposeViewController comes with some built-in methods to allow you easily do the upload. Let’s tweak the code of the Facebook button and make the upload work.
First, download this image and add it to the Xcode project. (You can use any image but make sure you name it as “socialsharing-facebook-image.jpg”)
You can simply use the “addImage” method to attach an image and the “addURL” method to include a link.
1
2
        [controller addURL:[NSURL URLWithString:@"http://www.appcoda.com"]];
        [controller addImage:[UIImage imageNamed:@"socialsharing-facebook-image.jpg"]];
The final code for “postToFacebook” should look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
- (IBAction)postToFacebook:(id)sender {
    if([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
       
        SLComposeViewController *controller = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
       
        [controller setInitialText:@"First post from my iPhone app"];
        [controller addURL:[NSURL URLWithString:@"http://www.appcoda.com"]];
        [controller addImage:[UIImage imageNamed:@"socialsharing-facebook-image.jpg"]];
       
        [self presentViewController:controller animated:YES completion:Nil];
       
    }
}
Go ahead to run the app and test out the Facebook feature again. You should see a thumbnail and a link bundled in the post.
SocialSharing Facebook Post with Image
Upload Post with image and link

Summary

As you can see from this tutorial, it’s pretty easy to add Twitter and Facebook feature using the Social Framework in iOS 6. If you’re building your app, there is no reason why you shouldn’t incorporate the social features. With Twitter and Facebook support, it adds values to your app and may boost its popularity.
The tutorial introduces the basics of Facebook and Twitter integration. You can try to tweak the demo app and upload multiple images to the social networks. However, if you want to access more advanced features such as display users’ Facebook friends, you’ll need to study the Facebook API.
I hope you enjoy the tutorial and you have a better understanding about the social framework. Feel free to leave your questions and share your thought about the tutorial.

iOS Programming 101: How To Send Email in Your iPhone App

Here comes another tutorial for our iOS Programming 101 series. Last time, we show you how to hide tab bar in navigation interface. In this tutorial, we’ll show you how easy you can let user send email in your app.
The iOS SDK has made it really easy to send email using the built-in APIs. With a few line of codes, you can launch the same email interface as the stock Mail app that lets you compose an email. In this tutorial, we’ll build a very simple app to show you how to send both plain text and HTML email using the iOS SDK.
SimpleEmail Tutorial Logo

Create a Simple View App with a Button

First, create a simple app with a view controller and a button. If you have no idea how to do it, you better revisit the Hello World tutorial. Let’s name the project as SimpleEmail. If you’ve successfully created your project, add a “Contact Us” button in the view.
SimpleEmail App with Contact Us Button
SimpleEmail App with Contact Us Button
What the app does is that it’ll show up the email interface when user taps the “Contact Us” button.

Connecting the Contact Us Button with Action

In the past tutorials, we used to add the action method manually in the header file of the view controller file. We then link the button and the action method in the Interface Builder.
This time, let us show you another way to add the action method (make sure you use Xcode 4.3 or up).
In the Project Navigator, select the “SimpleEmailViewController.xib” file to go to the Interface Builder. Switch to the Assistant Editor and hide the Utility area:
Show Assistant Editor
Show Assistant Editor and Hide Utility Area
Once you make the change, your Xcode environment should look like the below screen. The interface and its corresponding code are now shown side by side:
Assistant Editor Enabled
User Interface and Source Code Displayed Side by Side
Now we’ll add an action method for the “Contact Us” button. Press and hold the control key, click the “Contact Us” button and drag it towards the “SimpleEmailViewController.h”. As you place the pointer between the “@interface” and “@end” keywords, you should see a prompt that allows you to insert outlet and action.
Prompt to Let You Insert Outlet and Action
Prompt to Let You Insert Outlet and Action
Release the mouse button and Xcode prompts you to add the outlet/action. As we’re going to add the action method, select “Action” for “Connection” and name the method as “showEmail”. You can keep the event as “Touch Up Inside”. The “showEmail” method will be invoked when users lift up the finger inside the button.
Add action method showEmail
Add action method - showEmail
Once you confirm the change by clicking the “Connect” button, Xcode automatically adds the method declaration in the SimpleEmailViewController.h.
Added ShowEmail Action Method
Xcode Automatically Inserts the showEmail Method

Implementing the Email Interface

Next, import the “MessageUI.h” and implement the “MFMailComposeViewControllerDelegate” delegate in SimpleEmailViewController.h.
1
2
3
4
5
6
7
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>

@interface SimpleEmailViewController : UIViewController <MFMailComposeViewControllerDelegate> // Add the delegate
- (IBAction)showEmail:(id)sender;

@end
Select the “SimpleEmailViewController.m” and we’ll implement the “showEmail” method and MFMailComposeViewControllerDelegate. Add the following code in the implementation file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
- (IBAction)showEmail:(id)sender {
    // Email Subject
    NSString *emailTitle = @"Test Email";
    // Email Content
    NSString *messageBody = @"iOS programming is so fun!";
    // To address
    NSArray *toRecipents = [NSArray arrayWithObject:@"support@appcoda.com"];
   
    MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
    mc.mailComposeDelegate = self;
    [mc setSubject:emailTitle];
    [mc setMessageBody:messageBody isHTML:NO];
    [mc setToRecipients:toRecipents];

    // Present mail view controller on screen
    [self presentViewController:mc animated:YES completion:NULL];

}

- (void) mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
    switch (result)
    {
        case MFMailComposeResultCancelled:
            NSLog(@"Mail cancelled");
            break;
        case MFMailComposeResultSaved:
            NSLog(@"Mail saved");
            break;
        case MFMailComposeResultSent:
            NSLog(@"Mail sent");
            break;
        case MFMailComposeResultFailed:
            NSLog(@"Mail sent failure: %@", [error localizedDescription]);
            break;
        default:
            break;
    }
   
    // Close the Mail Interface
    [self dismissViewControllerAnimated:YES completion:NULL];
}
Line 3-7 of the above code define the email subject, message content and recipients. Line 9-13 creates the built-in MFMailComposeViewController. The MFMailComposeViewController class provides a standard interface that manages the editing and sending an email message. You can use this view controller to display a standard email view inside your application. We populate the fields of that view with initial values including the recipient email, subject and body text.
Line 13 of the code invokes the presentViewController to display the mail interface on screen.
The “didFinishWithResult:” is a method of the MFMailComposeViewControllerDelegate protocol. This method will be automatically called when the mail interface is closed (e.g. user cancels the operation). The result parameter tells you the result code when the mail composition interface is dismissed. For the sake of simplicity, we simply log the status in this example. In real world application, you should provide special handling for the result code (e.g. display an alert when the app fails to send the email).
Finally, line 41 dismisses the mail composition interface.

Adding the MessageUI Framework

However, this is not done yet. If you try to compile the app, you’ll end up with the below compilation error:
SimpleEmail Compilation Error
SimpleEmail App Compilation Error
The problem is that Xcode has no idea about what the “MFMailComposeViewController” is. Though “MFMailComposeViewController” is a built-in controller in iOS SDK, it’s developers’ responsibility to embed the necessary framework in your project. When the Xcode project is first created, it only comes with three core frameworks including UIKit, Foundation and CoreGraphics. The “MFMailComposeViewController” class is included in the MessageUI framework that you have to add manually.
To fix the error, we have to embed the framework in the project. In the Project Navigator, select “SimpleEmail” project and then select the “SimpleEmail” target under “Targets”. Click “Build Phases” at the top of the project editor. Then open the Link Binary With Libraries section.
Add Framework in Build Phases
Add Framework in Build Phases
Next, click the “+” button and select the “MessageUI.framework”. After you click the “Add” button, Xcode will include the MessageUI framework in the project.
Add MessageUI Framework
Add MessageUI Framework in Your Xcode Project
Now the error should have been fixed. Run your app and see how it works. Tapping the “Contact Us” button will show you the “Compose Email” interface with pre-populated content.
SimpleEmail App
SimpleEmail App

Composing HTML Email

The SimpleEmail app now only supports plain text email. You can easily enable the support of HTML email by changing the “isHTML” parameter in “setMessageBody” method from “N” to “Y”. Try to change the code in “showEmail” method to the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (IBAction)showEmail:(id)sender {
    // Email Subject
    NSString *emailTitle = @"Test Email";
    // Email Content
    NSString *messageBody = @"<h1>Learning iOS Programming!</h1>"; // Change the message body to HTML
    // To address
    NSArray *toRecipents = [NSArray arrayWithObject:@"support@appcoda.com"];
   
    MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
    mc.mailComposeDelegate = self;
    [mc setSubject:emailTitle];
    [mc setMessageBody:messageBody isHTML:YES];
    [mc setToRecipients:toRecipents];

    // Present mail view controller on screen
    [self presentViewController:mc animated:YES completion:NULL];

}
Compile and run your app again. With just a simple change, the SimpleEmail app now offers HTML support!
SimpleEmail App with HTML Support
SimpleEmail App with HTML Support
As always, leave us comment and share your thought about the tutorial. If you have any suggestion for the iOS Programming 101 series, feel free to let us know.

iOS Programming 101: How To Customize Tab Bar Background and Appearance

http://www.appcoda.com/ios-programming-how-to-customize-tab-bar-background-appearance/

With over 700,000 apps in App Store, your app must have a great design to stand out from others. If your app is still using the default design, you better give it a tweak and make it look better. I’m sure it’ll improve your app sales and attract more downloads.
When you check out any popular app, you’ll notice a custom design tab bar. Some readers asked how we can change the appearance of the tab bar. In this tutorial, we’ll show you how to do that. With the introduction of Appearance API in iOS 5, it’s much easier to custom the UI controls that gives your app a unique look and feel.

An appearance proxy is an object you use to modify the default appearance of visual objects such as views and bar items. Classes that adopt the UIAppearance protocol support the use of an appearance proxy. To modify the default appearance of such a class, retrieve its proxy object using the appearance class method and call the returned object’s methods to set new default values. A proxy object implements those methods and properties from its proxied class that are tagged with the UI_APPEARANCE_SELECTOR macro. For example, you can use a proxy object to change the default tint color (through the progressTintColor or trackTintColor properties) of the UIProgressView class.
As usual, we’ll build a sample app to walk you through the customization. The app doesn’t have any features but our primary focus here is to show you how to apply the Appearance API and change the appearance of tab bar including the background image and title color. We’ll also modify the images of UITabBarItem as well. Let’s first take a look at the final deliverable.
Custom Tab Bar Final Deliverable

Understanding UITabBar and UITabBarItem

Before we dig into the API, let’s first take a look at how the UITabBar and UITabBarItem are designed:
UITabBar and UITabBarItem Appearance
UITabBar and UITabBarItem Appearance
The above illustration should give you a better idea how you can customize the UI controls. Now let’s start to build the sample app.

Create a Sample Tab Bar App

First, create a new Xcode project using the “Tabbed Application” Template. Let’s name the project as “CustomTabApp” and set the project with the following parameters:
CustomTabApp - New Project
CustomTabApp – New Project
After Xcode created the project, download this image set and add all the images file to your Xcode project.

Add More Tabs to Tab Bar Controller

Go to Storyboard and design the interface. As the project is first generated, it comes with two tab bar items only. Let’s add two more. (Note: If you’re new to tab bar controller, check out our earlier tutorial about how to create a tab bar controller using Storyboard.)
Simply add two view controllers and associate them with the Tab Bar Controller. Press and hold the control key, click the Tab Bar Controller and drag it towards the new view controllers. Select “view controllers” for Relationship Segue.
Associates Two More View Controllers with the Tab Bar Controller
Associates Two More View Controllers with the Tab Bar Controller
Once done, you should have a Tab Bar Controller with 4 tabs. Run the app and this is how it looks like:
CustomTabApp with 4 Tabs
CustomTabApp with 4 Tabs

Change Title and Icon of the Tab Bar Items

Next, select the “CustomTabAppAppDelegate.m” and edit the “didFinishLaunchingWithOptions” method as below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Assign tab bar item with titles
    UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
    UITabBar *tabBar = tabBarController.tabBar;
    UITabBarItem *tabBarItem1 = [tabBar.items objectAtIndex:0];
    UITabBarItem *tabBarItem2 = [tabBar.items objectAtIndex:1];
    UITabBarItem *tabBarItem3 = [tabBar.items objectAtIndex:2];
    UITabBarItem *tabBarItem4 = [tabBar.items objectAtIndex:3];
   
    tabBarItem1.title = @"Home";
    tabBarItem2.title = @"Maps";
    tabBarItem3.title = @"My Plan";
    tabBarItem4.title = @"Settings";
   
    [tabBarItem1 setFinishedSelectedImage:[UIImage imageNamed:@"home_selected.png"] withFinishedUnselectedImage:[UIImage imageNamed:@"home.png"]];
    [tabBarItem2 setFinishedSelectedImage:[UIImage imageNamed:@"maps_selected.png"] withFinishedUnselectedImage:[UIImage imageNamed:@"maps.png"]];
    [tabBarItem3 setFinishedSelectedImage:[UIImage imageNamed:@"myplan_selected.png"] withFinishedUnselectedImage:[UIImage imageNamed:@"myplan.png"]];
    [tabBarItem4 setFinishedSelectedImage:[UIImage imageNamed:@"settings_selected.png"] withFinishedUnselectedImage:[UIImage imageNamed:@"settings.png"]];

    return YES;
}
The above code is very straightforward but let me explain the code line by line.
Line 4-9 – As we use the Tabbed Application Xcode template, the UITabBarController is assigned as the root view controller. From the tabBarController, we can retrieve each individual tab item.
Line 11-14 – Assign the title of the tab bar items
Line 16-19 – Set the images of the tab bar items. There are two types of images: FinishedSelectedImage and FinishedUnselectedImage. When user selects a tab item, the selected tab item will be highlighted with the “FinishedSelectedImage”, while the rest of the tab items will display the “FinishedUnselectedImage”.
When you run the app again, this is how it looks like:
CustomTabApp Tab with Icons
CustomTabApp – Tabs with Icons and Titles

Styling the Tab Bar

Next, we’ll change the background image of the entire tab bar and the selection indicator. As said before, the Appearance API makes it very easy to customize the background. Add the following code to the “didFinishLaunchingWithOptions” method:
1
2
3
    UIImage* tabBarBackground = [UIImage imageNamed:@"tabbar.png"];
    [[UITabBar appearance] setBackgroundImage:tabBarBackground];
    [[UITabBar appearance] setSelectionIndicatorImage:[UIImage imageNamed:@"tabbar_selected.png"]];
The code tells your app to use “tabbar.png” as the background image of tab bar (The dimension is 320 x 49 pixels) globally. We also update the selection indicator image that better fits with the new background.
Run the app again and you should now get a tab bar with better look and feel:
CustomTabApp with New Tab Bar Background
CustomTabApp with New Tab Bar Background

Changing the Text Color of Tab Bar Item

By default, the title color for the unselected tabs is in gray while the selected one is in white. To change the color we alter a dictionary of attributes with the UITextAttributeTextColor key:
1
2
3
4
5
6
7
    [[UITabBarItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
                                                   [UIColor whiteColor], UITextAttributeTextColor,
                                                   nil] forState:UIControlStateNormal];
    UIColor *titleHighlightedColor = [UIColor colorWithRed:153/255.0 green:192/255.0 blue:48/255.0 alpha:1.0];
    [[UITabBarItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
                                                       titleHighlightedColor, UITextAttributeTextColor,
                                                       nil] forState:UIControlStateHighlighted];
Add the above code to the “didFinishLaunchingWithOptions” method. For unselected tabs (i.e. with state of “UIControlStateNormal”), we change the text color to white. For selected tabs, we want to have a special green color that can’t be found in the UIColor class. Therefore, we initialize a new color object with specific color code (i.e. red: 153, green: 192, blue: 48).
Tip: If you’re looking for a better way to convert color in HEX format to UIColor, check out this simple macro.
That’s it! The final step is to run the app and check out the result. You should now have a fully customized tab bar.
CustomTabApp - Fully Customized Tab Bar
CustomTabApp – Fully Customized Tab Bar

Complete Code

For your easy reference, here is the complete code for the customization:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Assign tab bar item with titles
    UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
    UITabBar *tabBar = tabBarController.tabBar;
    UITabBarItem *tabBarItem1 = [tabBar.items objectAtIndex:0];
    UITabBarItem *tabBarItem2 = [tabBar.items objectAtIndex:1];
    UITabBarItem *tabBarItem3 = [tabBar.items objectAtIndex:2];
    UITabBarItem *tabBarItem4 = [tabBar.items objectAtIndex:3];
   
    tabBarItem1.title = @"Home";
    tabBarItem2.title = @"Maps";
    tabBarItem3.title = @"My Plan";
    tabBarItem4.title = @"Settings";
   
    [tabBarItem1 setFinishedSelectedImage:[UIImage imageNamed:@"home_selected.png"] withFinishedUnselectedImage:[UIImage imageNamed:@"home.png"]];
    [tabBarItem2 setFinishedSelectedImage:[UIImage imageNamed:@"maps_selected.png"] withFinishedUnselectedImage:[UIImage imageNamed:@"maps.png"]];
    [tabBarItem3 setFinishedSelectedImage:[UIImage imageNamed:@"myplan_selected.png"] withFinishedUnselectedImage:[UIImage imageNamed:@"myplan.png"]];
    [tabBarItem4 setFinishedSelectedImage:[UIImage imageNamed:@"settings_selected.png"] withFinishedUnselectedImage:[UIImage imageNamed:@"settings.png"]];

   
    // Change the tab bar background
    UIImage* tabBarBackground = [UIImage imageNamed:@"tabbar.png"];
    [[UITabBar appearance] setBackgroundImage:tabBarBackground];
    [[UITabBar appearance] setSelectionIndicatorImage:[UIImage imageNamed:@"tabbar_selected.png"]];
   
    // Change the title color of tab bar items
    [[UITabBarItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
                                                       [UIColor whiteColor], UITextAttributeTextColor,
                                                       nil] forState:UIControlStateNormal];
    UIColor *titleHighlightedColor = [UIColor colorWithRed:153/255.0 green:192/255.0 blue:48/255.0 alpha:1.0];
    [[UITabBarItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
                                                       titleHighlightedColor, UITextAttributeTextColor,
                                                       nil] forState:UIControlStateHighlighted];


    return YES;
}

What’s Next?

In this tutorial, we show you the basics about how to change the appearance of tab bar using Appearance API. If you’ve already developed an app or you have completed the Restaurant App tutorial, go ahead to tweak the app and make your own tab bar.