Monday, May 9, 2011

Making your first iPhone app

Making your first iPhone app is about getting familiar with the tools and the SDK.

So let us start off, first of all open up XCode and click on new project in the file menu. In the iPhone tab you will be presented with a lot of types of projects, select window based application, click next, name the project myFirstApp.

Now you will have your working environment, i.e Xcode set up with some files with code in it.

iOS development is based on the Model-View-Controller approach, and it involves extensive use of viewControllers. View controllers are classes which draw view on the device's screen. The class is called UIViewController and most of the times this class will be subclassed to implement your own code. We will also have to do the same. To do this click on new file in the file menu and select the UIViewController subclass, name it FirstViewController and check the options for adding a .h file and a .xib file.

Now to add the view controller add the following code to myFirstAppDelegate.h.

First of all we have to include FirstViewController.h in the appDelegate. You do this by adding the following line on the top of the file

#import "FirstViewController.h"


Now we declare the view controller object in the app delegate. To do this we add the following line inside the @interface brackets


FirstViewController *viewController;


And then after the bracket close we add one more line


@property (nonatomic, retain) FirstViewController *viewController;


Now we move on to the myFirstAppDelegate.m inside the applicationDidFinishLaunching method. 

Now that you have the basic structure of you app ready, it is time to put in some code. The basic ways of interaction of your user with your apps will be through buttons and labels, let us do that. To do that we will use interface builder, a visual tool to design the interface of your app. The xib file that got added to your project when you created the new view controller subclass is an interface builder file. Double click this file to open up this file in interface builder.

Let us first add a button to the app. To do that search for 'UIButton' in the library window and drag it to your view. Resize and name it as you want. Similarly we add a label by searching for 'UILabel' in the library window and add it to your view.

Go back to XCode to FirstViewController.h, inside the @interface add declarations for the label. To do this add the following lines

UILabel *firstLabel;


Outside the brackets add the following lines


@property (nonatomic,retain) IBOutlet UILabel *firstLabel;


What the four lines above do it that they tell the app that we have one label. The IBOutlet keyword in the last line is for interface builder to know that there is one label we have declared in our code.


What we plan to do is to display the number of times the button is pressed on the label. So as an when the button is pressed the count on the label will get incremented by one. To do this we have to call a method whenever the button is pressed and in that method increment the count on the label.


Let us name this method buttonPressed, to tell the app to call the method whenever the button is pressed we need to connect the method and the button through interface builder, but for that we will have to add one line of code in the .h file below the @property line.


-(IBAction)buttonPressed;


This will tell interface builder that this method has been declared in code. Save everything and jump over to interface builder and right click on files owner, you should see the firstLabel you declared, drag the small circle besides the firstLabel to the label in your window/view. This now connects the variable firstLabel to the actual label in the view. Do the same thing for the method buttonPressed, drag its circle to the button and you should see a list of actions, select the touch up inside action.

With this all your connections are established and the only thing left to do is write the code for incrementing the count. Go to the FirstViewController.m file and add the following line

@synthesise firstLabel;


This line is to synthesise the property we had added in the FirstViewController.h file. Don't worry you don't have to care too much about this right now.


As you would expect when the app first starts the count should be zero. To do this find the viewDidLoad method in FirstViewController.m and uncomment it. Add the following lines


firstLabel.text = [NSString stringWithFormat:@"%d",0];


 Now to implement the method buttonPressed. 


-(IBAction)buttonPressed
{
      NSInteger num = [firstLabel.text intValue];
      num++;
      firstLabel.text = [NSString stringWithString:@"%d",num];
}


Save everything and build the project. If everything goes well you will have your app running!

In an extension to this tutorial we will add code to the existing app that will save state, i.e the count so that when you open the app again after closing the count gets retrieved.




Modal Views

Many apps that require the user to sign in present a view sliding up from the bottom of the screen, this is called a modal view. Sliding-up is just one way a modal view can be presented, other ways are partial curl like in the maps app, the flipping view when you tap the 'i' button etc.

Partial curl in maps
So the idea of a modal view is to present a temporary view which asks the user to perform some action and then the view is dismissed to reveal the original view. The idea of a sign in perfectly fits into the reason of a modal view being presented, the user is doing something that requires signing in, the modal view is presented, the user logs in and the original screen comes back to let the user continue his/her activity in the app.

So let us get to know how is this done in code. First you'll need two view controllers, one will be the main view and the second will be the modal view. Set up the first view controller to have a button which is hooked up to a method called buttonPressed. In this method put the following code to present the second view modally.

SecondView *modalViewController = [[SecondView alloc] init];
[modalViewController setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self presentModalViewController:modalViewController animated:YES];

If everything goes well when you build the app and press the button, a new view should slide from below. 

To make the view appear in other styles like horizontal flip use the following pass the following parameters instead of UIModalTransitionStyleCoverVertical
  • Horizontal flip - UIModalTransitionStyleFlipHorizontal
  • Partial curl - UIModalTransitionStylePartialCurl
  • Dissolve - UIModalTransitionStyleCrossDissolve
Try running the project with each of these as arguments to have a look at all the animations.

Now that we have successfully managed to present view controllers, we move on to dismissing them, that is bring back the original view on the screen from where the modal view was presented.

For this add a button in your secondView which hooks up to a method, lets call it otherButtonPressed. Include the following code in the implementation of the otherButtonPressed method.

[self dismissModalViewControllerAnimated:YES];

Run your project now and you should have a sample app which presents and dismisses your modal view. You can experiment with the parameters, try out different styles.

Sunday, May 8, 2011

Delegation

On your way to developing apps you will encounter many situations when you would want to respond to certain events in your app but you would find it difficult to implement such actions in code. 

For example, you are downloading a file from the internet and you want to constantly update the progress on the screen for your user. Now to actually download stuff from the internet you would use built in classes like NSURLRequest which have been built by Apple. Now what Apple does in order for you to actually accomplish the task of showing progress is that, it tells the class NSURLRequest to send messages while it is downloading, to a class of your choice. So the NSURLRequest class is delegating tasks that it should be doing to a class of your choice. This class of your choice is known as delegate.

I guess the concept should be very clear by now, some class sends messages to some other class so that the other class may complete tasks that the first class should have done.

Let us take another example where this is used, the TableView. The TableView is used in many iOS apps including Mail and iPod. The table view has cells, and each of those cells contain data. Many a times when you tap on a cell it does some action, for ex in the iPod app when you tap on a song it starts playing it. This is done by delegation. 


So whenever a cell is tapped on a table view a message is sent to a class defined by you, let us call that class yourClass. Now what is meant by sending a message is that a predefined method specified and decided by Apple engineers is called in yourClass. In the case we are discussing, this method is tableView didSelectRowAtIndexPath is called when a cell is tapped.

You have to implement this method in yourClass and in that you can include code to take whatever action you want in response to the cell-tapping. In case of the iPod app this method will start playing the selected song.

For detailed instructions on how to include a tableView in your app refer to this post.

If you have still not got a clear idea about delegation I am very sure when you actually start delving deeper and deeper into iOS development your concepts will become clearer.


Saturday, May 7, 2011

Objective-C Syntax

For a first timer coming from a language like C or PHP, objective C syntax does seem weird, but it takes only a few days to get familiar with it.

The most striking difference in Objective C syntax is the way to call methods. In C or PHP when you call a method of a class through an object its something like this

returnvalue = objectname->methodCallWithTwoParameters(n1,n2);

However in Objective C the call is something like this

returnValue = [objectName methodCallWithParameterOne:n1 parameterTwo:n2];


As you see the parameters are passed in the middle of the method name. The whole call is wrapped with square brackets.

NSUserDefaults

This class helps you to easily save data (mostly preferences) to the iPhone so that you can recover it later.
So if you have an NSString, NSDictionary, NSArray,BOOL, NSDate or NSNumber you can easily use NSUserDefaults to store data.

In the background the system stores all these data types in plists, so NSUserDefaults is also a convenient method to deal with plists.

To do this you would first want to get a reference to the object of this class. This is done by calling this method
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];


This is a shared object so even if you create two references to it, it will ultimately be the same. 


Now let us initialise a few variables so that we may store it for later use.


NSString *name = [NSString stringWithString:@"John"];
NSArray *subjects = [NSArray initWithObjects:@"Physics",@"Maths",@"Management",nil];
NSDate *joinDate = [NSDate date];


We have three variables which we need to store into the system.
This is done by the following code


[userDefaults setObject:name forKey:@"Name"];
[userDefaults setObject:subjects forKey:@"Subjects"];
[userDefaults setObject:joinDate forKey:@"Date"];


Each method call stores one object into memory. 
You can retrieve the saved data through the key so it is important to name it something which is relevant to the data being stored.


Now that we have successfully had a look at the code to store data let us move on to retrieving that data. For that you should have a reference to the NSUserDefaults object. The method objectForKey returns the stored data (in case of BOOL it is boolForKey: ) So let us retrieve the data we stored.

NSString *savedName = [userDefaults objectForKey:@"Name"];
NSArray *savedSubjects = [userDefaults objectForKey:@"Subjects"];
NSDate *savedDate = [userDefaults objectForKey:@"Date"];


All of the above discussion was for objects, but there are a few data types like integers and floats which aren't objects but you might need to store them. The SDK has specific methods for each of them, here they are:

setInteger:forKey:,integerForKey: 
setBool:forKey,boolForKey: 
setFloat:forKey,floatForKey: 
setDouble:forKey,DoubleForKey: 

Even now one important question hasn't been answered yet, which is, when to save and retrieve this data?


If this data is required at the start of the application itself this it would be a good idea to retrieve saved data in the applicationDidFinishLaunching method.

You would want to save data when the home button is pressed, i.e your application is going to get closed or put into the background (iOS 4 and later). So the code for saving data should be put in applicationWillTerminate: and applicationWillResignActive:

With this you should be able to effectively save state of your application and save user data.









Friday, April 29, 2011

UINavigationController

This design pattern presents a hierarchy of views, one leading into the other when something is tapped. The class used for implementing the is UINavigationController. The settings app is a well known example of an app that has its core functioning based on the navigation controller and table views.


When you add the navigation controllers view to the window it will automatically add a navigation bar. The first view of the view controller is known as the root view.

Let us make a simple app which utilizes navigation controllers to present multiple views one after the other. Fire up XCode and click on a windows based app under projects. It sets up an app delegate and a nib file.

Now in XCode create a new UIViewController sublass along with a nib from the new file menu. Name is rootViewController. It will generate a .h, .m and nib file.

Again create a new UIViewController subclass and name it nextViewController. This also will generate three files.

Now go to the .m file of the app delegate and import the first classes we declared. The statements would be like these

#import "rootViewController.h"


Inside the applicationDidFinishLaunching method in the implementation file of the app delegate declare intances of both these classes

rootViewController *firstView = [[rootViewController alloc] init];

Now we have to present this view as the first view in the navigation pattern. To do that we will create an instance of UINavigationController and add firstView as its rootViewController.

UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:firstView];

Now we tell this app to add the navigation controller's view to the app window

[window addSubview:navController.view];

Now that we no longer need a reference to firstView, we release it to properly handle memory

[firstView release];

Go to the .h file of of the rootViewController, and add a method declaration buttonPressed
-(IBAction)buttonPressed:(id)sender

We have added the IBAction return type since we plan to hook this method to a button in Interface builder. This button will tell the navigation controller to present the next view in the hierarchy which is the nextViewController.

Go to the .m file of the rootViewController and implement the method we declared in the header file.
Also add the following line

#import "nextViewController.h"

The method will bring in the next view. The code will be like

-(IBAction)buttonPressed:(id)sender
{
nextViewController *nextV = [[nextViewController alloc] init];
[self.navigationController pushViewController:nextV;
}

Now you set up a button in Interface builder, hook it up to this method and you're done.

Sunday, April 24, 2011

Mimicking popular iOS apps design patterns

If you are an app junkie like I am, many a times you would want to imitate a popular app's UI in your own app, for ex the pull to refresh introduced in twitter for iPhone (tweetie back then). But you may not be very comfortable with UIViews, which are essential for designing these types of interfaces, for this open source projects come to the rescue. The open source port of the pull to refresh feature was then adopted in a lot of other apps including facebook.

A lot of other popular patterns like the iOS home screen, center button in tab bar (made popular in instagram), coverflow etc have open source ports, but the problem is that it is difficult to find the github (or where ever the source code is available) link for these projects.

Enter http://cocoacontrols.com , a repository of all such open source ports which has a rating system and a leaderboard as well. So the next time you want to mimic a UI pattern in your own app head to cocoa controls and look for it, in case you like it be sure to rate it as well for the benefit of others. 

Memory Management

An important concept in programming is memory handling. If you come from C you might know of pointers, they point to a certain memory location. So if you declare
int *num
The num variable will point to a certain location in memory. To reserve this memory for future use in C malloc or calloc is used, and after this space is reserved it is totally our responsibility to handle it, the system won't use this space at all during the execution of the program. So let us reserve 10 bytes of memory by using malloc and letting num point to that block of memory. Now in case you have done all of this in a function, the memory is reserved though out runtime but the num pointer won't be accessible outside the function. So oustide the function even though the memory is reserved you won't be able to access that memory and make changes to it.


Memory management in iOS is also very similar to this, almost all variables in iOS are pointers and memory is allocated to it through the alloc function. For ex if you want to allocate memory to an NSString pointer variable, you would do something like
NSString *string = [[NSString alloc] init];


So now the string has been allocated memory and you may use it in your code. Now since you are the one who allocated memory to the string you should be the one to deallocate memory from it. Now the SDK offers a dealloc method which you can call explicitly to free up the allocated memory but this isn't considered good practice, instead the SDK provides a convenient way to tell the OS that you have done your bit towards memory handling and now it is totally the system's responsibility to take care of the memory and ensure that it doesn't leak. This practice comes in handy when the object is needed by the system but you don't need a reference to it anymore, for ex after adding a viewcontroller to the navigation controller, a reference to the view controller isn't generally required. So you would tell the OS that I am releasing the object from my side and now it is your responsibility to take care of it. This code fragment will better explain the view controller and navigation controller example
UIViewController *vc = [[UIViewController alloc] init];
UINanigationController *navController = [[UINavigationController alloc] initWithRootViewController:vc];
[vc release];


So in the first line we allocate memory to the view controller, in the second line we allocate memory to a navigation controller and assign the previously declared view controller as the navigation controllers root view controller. After doing this we no longer need a reference to vc so we call the release method on vc and tell the os to take care of the memory,


So whenever you call alloc be sure to call release otherwise you will create a memory leak and increase the memory footprint of your app, you sure don't want that to happen.

Most common ios design patterns

When you have limited screen real estate design becomes very important. Putting in a lot of data without making the screen cluttered in very important when designing applications. This takes a lot of thinking and fortunately the engineers and ui experts at apple have done this thinking for you. They have provided easy to use design patterns in their sdk for making good, presentable and usable apps.

Some of these deign patterns are

  • Tab Bar
  • navigation bar
  • table views
  • toolbars
Tab Bar
This design pattern presents a bar at the bottom of the screen with 3-5 icons on it which present different views. 

Navigation bar

This patterns presents a hierarchy of views, which are related providing mechanisms to move back and forth in the heirarchy.

Table View
This view presents a scrollable list of items with each item very often presenting a view of its own. It is extremely effective in presenting a lot of data in limited screen size. 

Tool bar
This was introduced in iOS 3.0 (it was called iPhone OS back then), its position is same as the tab bar, i.e at the bottom of the screen. You can see it in safari, mail and a lot of other applicaitons

Personal opinion, I believe putting a toolbar on top of a tab bar is a horrible idea.

For further reading you can refer to apple's iOS Human Interface Guidelines ,
also pttrns is a great site which assembles the best UIs in the AppStore for your reference http://pttrns.com/ 


plists

If you have ever gone through the ios filesystem you will find lots and lots of plists. Plists or property lists are basically xml files used to store information on the iphone.

A plist can store arrays, strings, nsdata, numbers, dates and nsdictionaries.



A plist has a basic structure, with one root element and everything under it.

Let us make a plist to save contacts (this may be a bad practice and is only for illustration purposes)
So to start with let the root element of our plist be an array which will hold all the contacts.
Each element of the array will be an nsdictionary with key value pairs as follows

  • id - nsnumber
  • name - nsstring
  • phone - nsstring
It is a very simple structure and the iOS sdk offers a lot of convenience methods to load data from plists into arrays or dictionaries.

So during the first run of our program we would want to create a plist and save it to some locations, this location will most likely be your documents directory since it is automatically backed up by iTunes.

So first we need to get the path for the documents directory of our app, we get this through the following code 

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *writeReadPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"contacts.plist"];

As you see the second line has the filename of the plist appended to the path of the documents directory we got, in this case we have named the file to be contacts.plist .

Now that we have got the path to our file, let us proceed to writing data on our file. If it is the first run of the app there is a possibility the file doesn't exist, to tackle this issue we add a few lines of code and create the plist with sample data

NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:writeReadPath]) {
     NSDictionary *contact1 = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects:[NSNumber numberWithInt:1],@"John",@"1944232321",nil] forKeys:[NSArray arrayWithObjects:@"id",@"name",@"phone",nil]];
 NSDictionary *contact2 = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects:[NSNumber numberWithInt:2],@"Steve",@"1944232421",nil] forKeys:[NSArray arrayWithObjects:@"id",@"name",@"phone",nil]];
 NSDictionary *contact3 = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects:[NSNumber numberWithInt:3],@"Peter",@"1944132321",nil] forKeys:[NSArray arrayWithObjects:@"id",@"name",@"phone",nil]];
     NSArray *contacts = [NSArray arrayWithObjects:contact1,contact2,contact3,nil];
[contacts writeToFile:writeReadPath atomically:YES];
}

With this much of code we have managed to create a new plist file, add contacts to it, without even going to deep into file handling. Thanks to the convenience methods of nsarray and nsdictionary it becomes very easy to write data into plists. In future posts we will deal with editing and deleting items from a plist.

UITabBarController

This is another common design pattern found in iOS apps, it includes a bar (generally black) at the bottom of the screen with various icons which when tapped load up different views.

tabbar

Each icon (button) is actually a separate viewController with the title of the viewController displayed below each of the icon.

The uitabbarcontroller has a viewControllers property to which an array of viewControllers is assigned. Generally tabbarcontrollers have four or five viewControllers. In case there are more than 5 view controllers a more icon is created like the one seen above which has the rest of the viewcontrollers.

Saturday, April 23, 2011

UITableView

The UITableView is a very common design pattern used in iOS apps. They help in presenting a lot of data in limited screen real estate.



Setting up a UITableView requires a delegate and a data source to be implemented. In case you're not familiar with the delegation and data source concepts, think of it like this, the delegate is a class which tells the OS, how to present the table view, for ex its size, the modes in which the table view should be like editing, normal etc. The data source, as the name suggests provides data to the table view to present it on the screen.

This was about the concept of delegation and data source, to actually implement it, you should declare one of your classes (view controller, preferably with a nib file as well) as the UITableViewDelegate and the UITableViewDataSource. This is done by adding <UITableViewDelegate>, <UITableViewDataSource> after the class declaration in the header (.h) file, like this :

@interface MainViewMulti : UIViewController <UITableViewDelegate,UITableViewDataSource> {
//class members
}

To actually add the table view you can either do it through code or interface builder. Interface builder is preferred if you have relatively simple tasks. So click on the nib file linked with your view controller, it will open interface builder. Now in the library search for tableview and drag it to your nib.



After doing that right click on the table view you just dragged, there will be delegate and datasource outlets, drag it to the files owner. This tells the table view that the class you've declared is its delegate and data source.


Now that you have declared your class as the delegate and the data source it is time to implement mandatory methods which will provide data and set up the the tableviewcells.

The apple documentation says that the following methods are mandatory


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

The first method tells the device, how many rows do you want, that value is specified by the return value of that method.

The second method tells the device what contents to put in each row of the table view. This method is called for each row.

Right now you have the basic framework required for setting up a table view. You can use this as a template for all of you tableviews.

Now to actually put data in your table view let us declare an array in the header file, and populate it with nsstrings. Let us name the array tableDataSource, to populate it insert the following code in your viewDidLoad method


tableDataSource = [[NSArray alloc] initWithObjects:@"Monday", @"Tuesday", @"Wednesday", @"Thursday", @"Friday", @"Saturday", @"Sunday",nil];

In case you aren't familiar with arrays, this is one of the convenience methods to directly assign an array with objects.

Now the table view will contain as many rows as the number of objects in the array, so to tell this to the os add the following line to your -  numberOfRowsInSection method
return tableDataSource.count

The only thing left now is to populate each row of the tableview with the items in the array, to do this add the following code to your cellForRowAtIndexPath method


static NSString *SimpleTableIdentifier = @"SimpleTableIdentifier";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier] autorelease];
}

NSUInteger row = [indexPath row];
cell.textLabel.text = [tableDataSource objectAtIndex:row];
return cell;

Now save everything (including the nib files) build your project and you should see the table view with the items you set in the simulator.

Next we will discuss how to put the table view in edit mode and how to add and delete items from the tableview.