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.
iOS development
Monday, May 9, 2011
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.
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.
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.
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.
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.
Subscribe to:
Posts (Atom)