JavaBeat

  • Home
  • Java
    • Java 7
    • Java 8
    • Java EE
    • Servlets
  • Spring Framework
    • Spring Tutorials
    • Spring 4 Tutorials
    • Spring Boot
  • JSF Tutorials
  • Most Popular
    • Binary Search Tree Traversal
    • Spring Batch Tutorial
    • AngularJS + Spring MVC
    • Spring Data JPA Tutorial
    • Packaging and Deploying Node.js
  • About Us
    • Join Us (JBC)
  • Privacy
  • Contact Us

UITableView in iOS

May 20, 2014 by itadmin Leave a Comment

UITableView is a type of a view used to display the data in the form of a table. The UI control consists of one column and the number of rows can be specified by user. It inherits from UIView, UIResponder and NSObject classes. UITableView control is present in the object library in Xcode. It consists of cell of type UITableViewCell which forms the rows. The cell consists of content view, accessory view which helps us to display data and perform certain action. Currently there are 2 different styles of tableview, Plain and Grouped table view.

In this tutorial we will see how to use UITableView in a singleView application, populate the data to the table view by specifying number of rows and sections, perform some action when a row is selected.The tableview style is Plain.

The following concepts are covered in this document.

  1. Save data in Collections(here we use NSMutableDictionary)
  2. UITableViewDatasource protocol methods for populating data.
  3. UITableViewDelegate protocol methods for performing an action when a cell is selected.

Lets take an example of groceries list which we have to buy from a shop. List the items in the tableview and once we buy the product we mark the product in the tableview by using a check mark, check mark is accessory which can be used in UITableView.

Single View Application in XCode

  • create a single view application in Xcode, name the project as “UITableViewDemo”.
  • In Main.storyboard, a view is present in the viewcontroller, drag and drop a UITableView from the object library.

addTableView

Declare the properties

  • Connect the table view present in interface to the property.
  • Declare the remaining properties required.

[code]
@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UITableView *itemsTableView;
@property (strong,nonatomic) NSMutableDictionary *itemDetailsList;
@property  (strong,nonatomic) NSArray *allKeys;
@end
[/code]

Save data in NSMutableDictionary

  • We need to have some data to display in the tableview. In this example we store data in NSMutableDictionary. NSMutableDictionary is a dictionary with key-value pair that allows to modify the data present in the dictionary. It inherits from NSDictionary with modification operations. In the below code we store the item name as the key and “YES” or “NO” as the bool value to identify whether the item is purchased or not.
  • We also assign all the keys of the dictionary to NSArray, as we have to display only keys in the tableview.

[code]
self.itemDetailsList = [[NSMutableDictionary alloc]init];
[self.itemDetailsList setObject:[NSNumber numberWithBool:NO] forKey:@"Whole-wheat bread"];
[self.itemDetailsList setObject:[NSNumber numberWithBool:NO] forKey:@"Brown rice"];
[self.itemDetailsList setObject:[NSNumber numberWithBool:NO] forKey:@"Tomato sauce"];
[self.itemDetailsList setObject:[NSNumber numberWithBool:NO] forKey:@"Red-wine vinegar"];
[self.itemDetailsList setObject:[NSNumber numberWithBool:NO] forKey:@"Mustard"];
[self.itemDetailsList setObject:[NSNumber numberWithBool:NO] forKey:@"Apples"];
[self.itemDetailsList setObject:[NSNumber numberWithBool:NO] forKey:@"Cakes"];
[self.itemDetailsList setObject:[NSNumber numberWithBool:NO] forKey:@"eggs"];
[self.itemDetailsList setObject:[NSNumber numberWithBool:NO] forKey:@"Sunscreen"];
[self.itemDetailsList setObject:[NSNumber numberWithBool:NO] forKey:@"broccoli"];

self.allKeys = [[NSArray alloc]initWithArray:[self.itemDetailsList allKeys]];
[/code]

UITableViewDataSource Protocol

UitableViewDataSource is a protocol which is used to construct and modify the tableview.  The protocol consists of many methods, the 3 important methods are:

  1. numberOfSectionsInTableView:   the method is used to specify the number of sections in the tableview, in our example we have only one section. Based on the number of sections the tableview is divided vertically.  The method is optional.
  2. tableView:numberOfRowsInSection: the method is used to specify the number of rows in each section. It is a required method in the protocol.
  3. tableView:cellForRowAtIndexPath:  the method is used to fill the cells with data. The method is called of reach row, and we are responsible to provide the appropriate  data for each cell. It is a required method.

When the tableview is reloaded or refreshed, the datasource is responsible to populate the tableview with the data. First the number of section is called to get the sections and then the no. of rows in a section  and for each row,  cellForRowAtIndexPath is called.

In order to use the protocol, we need to conform to the protocol UITableViewDataSource in .h file and set tableview’s datasource to current instance of the class(self), the code is given below.

In ViewController.h

[code]
@interface ViewController : UIViewController<UITableViewDataSource>
[/code]

In ViewController.m(the code should be present under viewDidLoad method)

[code]
self.itemsTableView.dataSource = self;
[/code]

Implementing UITableViewDataSource protocol methods

  • Since we are having only one section in the tableview, integer value 1 is returned.

[code]
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
[/code]

  • The number of rows is the items present in the dictionary.The count of the dictionary is returned as the number of rows.

[code]
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.itemDetailsList count];
}
[/code]

  • Load the cells with data.

[code]
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if(cell == nil){
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}

// Configure the cell…
cell.textLabel.text =[self.allKeys objectAtIndex:indexPath.row];
return cell;
}
[/code]

  • Create an instance of UITableViewCell and set it to nil. In the above method of loading the cells, we try to reuse the cells which are already created, so that the memory is not allocated for the cell again.
  • In our example, when the tableview is displayed for the first time, new tableviewcell is created for the cells which are visible in the simulator initially, memory is also allocated for all the cells and the cell’s content is set.when the table view is scrolled, the same cells are reused  by just changing the content of the cell thus by saving the memory.In this way we can effectively manage the memory.
  • Create an identifier of the cell of type NSString, which is used to identify a type of a cell that you want to create.TableView checks for the cell, whether the cell is already created by giving cellIdentifier as the parameter, using the method “dequeueReusablecellWithIdentifier”. The method returns the cell if it is already created before, otherwise it returns nil.
  • If it is nil, then, allocate memory for a cell by specifying the cell style and by giving the identifier.
  • Now that we have the cell, we can set the properties of the cell.Here we are setting the text for the label which is present in the cell.
  • Normally cell contains ContentView and accessory view.You can also set other properties for the cell namely textlabel for the title, detailTextLabel for the subtitle and an imageview for the thumbnail in content view.

Run the application. We can see the tableview with the list of items.

tableviewpopulated

Implementing UITableViewDelegate protocol methods

  • Our next requirement is to check and uncheck the items ,on selection of the cell which tells us that the item is being purchased or not. If the item is purchased then the value of the item in the dictionary is set to YES otherwise the value is set to NO. To achieve this we have to make use of the accessory view present in the cell. We have to set the accessory for the cell when the user taps or selects the cell in the tableview.
  • To perform some action when we interact with the tableview, we make use of UITableViewDelegate protocol. Conform to the protocol in .h file as shown below and set the delegate to current instance(self) of ViewController class.

In ViewController.h

[code]
@interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>[/code]

In ViewController.m (the code should be present under viewDidLoad method)

[code]
self.itemsTableView.delegate = self;
[/code]

  • There are several methods present in the UITablveiwDeleagte protocol, the method “didSelectRowAtIndexpath” is called when the user taps on the cell. We will implement the method to achieve the functionality which we require.

[code]
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

if(cell.accessoryType == UITableViewCellAccessoryCheckmark){
[cell setAccessoryType:UITableViewCellAccessoryNone];
[self.itemDetailsList setObject:[NSNumber numberWithBool:NO] forKey:[self.allKeys objectAtIndex:indexPath.row]];
}
else{
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
[self.itemDetailsList setObject:[NSNumber numberWithBool:YES] forKey:[self.allKeys objectAtIndex:indexPath.row]];
}
}
[/code]

  • In the above code, on selecting the cell, identify whether the cell is having checkmark, if it contains,  set its accessory type to none and update the dictionary by setting the item value to “NO”, which tells us that the item is not purchased.If the cell does not have checkmark, then set the accessory view to accesorycheckmark and the update the dictionary accordingly.
  • One last change should be made in “didSelectRowAtIndexPath” to make our application work correctly. Since we reuse the cell, we should also update the accessory type of the cell along with the textLabel while loading. The complete code for “didSelectRowAtIndexPath” is given below.

[code]
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if(cell == nil){
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}

// Configure the cell.

cell.textLabel.text =[self.allKeys objectAtIndex:indexPath.row];

//Set the accessory type for the cell

BOOL selectedVal = [[self.itemDetailsList objectForKey:[self.allKeys objectAtIndex:indexPath.row]]boolValue];
if(selectedVal == YES) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else{
cell.accessoryType = UITableViewCellAccessoryNone;
}

return cell;
}
[/code]

UITableView in iOS Demo

finalApp

Filed Under: Apple Tagged With: iOS, XCode

IOS Tutorial : Hello World Application using Xcode 5.0

May 9, 2014 by itadmin Leave a Comment

Xcode 5.0 is an IDE used for software development. It is a tool developed by Apple. Xcode 5.0 and later helps you to design and develop iOS application for iOS 7 and Mac OSx. You can download the IDE from apple developer website for Mac OS.

Let us start developing our first application in Xcode,  “Hello World” application, which displays a message “Hello World” in  iPhone simulator. The below application is a single view application, the application consists of interface(.xib file) which contains a label that displays a message “Hello World”. It is a very simple application that gives us an idea of how to use Xcode to create, run and debug the application.

1. Create XCode Project

Create new Xcode project. Open Xcode application, click on File->New->Project, a window opens which is shown below. Choose iOS from left panel and “Single View Application” from right panel and click Next.

Create XCode Project

Type your project name “HelloWorldApp” and you can give your organization name and company identifier. These details helps you to create “Bundle Identifier” which is used while submitting your app to app store and it should be unique from other applications present in your app store.

XCode Options

2. Files in Project Navigator

Now that the project is created, we can look into few files present in the project navigator.

  • “main.m” file is present under “Supporting File” group, calls the “AppDelagate” class which in turn launches the application.
  • AppDelegate.h and AppDelegate.m are the application delegate class, which helps to launch the application, “didFinishLaunchingWithOptions” function can be used to perform any action while launching the application. The class also helps us to manage the application when it goes to background or comes to foreground etc., there are delegate methods present in the AppDelegate class.
  • Main.Storyboard consists of a view controller. The view controller contains a view where we can design our UI.
  • ViewController.h and ViewController.m files are used to control the view, by default the view in Main.Storyboard is mapped to the ViewController class.You can check it out in the class attribute in Identity Inspector(Snapshot is given below).

Files in Project Navigator

XCode Files Navigator

3. Designing User Interface

Drag and drop a label to the view from Object library from the right panel as shown below.

XCode Designing User Interface

4. Connecting UILabel to ViewController

Connect the outlet UILabel to the viewcontroller class so that we can acces theUILabel and modify the properties of UILabel.

  • Click on show assistant editor in the tool bar to display its controller class (ViewController.h) on the right side.

Connecting UILabel to ViewController

  • Select the label in the view, cntrl- click and drag the control to ViewController.h and insert an outlet with the name for UILabel as “messageLabel” and click “Connect” as shown below.

Snapshot6

5. XCode Example Application

Once we have created a outlet and connected to the viewcontroller class, we can start coding.

  • The following code will be present in ViewController.h class when we connect the outlet UILabel.

[code]#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UILabel *messageLabel;
@end
[/code]

  • Write the following code in ViewController.m class to display the message “Hello World” when we run the application.
  • On loading the view, we are setting the text property of the label. The code is written in “ViewDidLoad” method.

[code]@interface ViewController ()
@end
@implementation ViewController

– (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

self.messageLabel.text = @"Hello World";
}

– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end

[/code]

6. Build and Run The XCode Application

  • Now we have completed the application, let us build and run the application.
  • In the menu bar, click Product->Build or Command+B to build the application.
  • In the menu bar, click Product->Run or Command+r or symbol  RunSymbol  to run the application.
  • We can also select the simulator by clicking on “set Active scheme”

XCode Run Application

When we run the application, the application looks like below,

XCode Hello World Application

7. Debugging

To debug, put a break point as shown below and build. The control stops at the break point when we run the application and we can resume, or step into or step over the function by using the options shown in the below snap shot.

XCode Debug

Snapshot10


Filed Under: Apple Tagged With: iOS, XCode 5

Accessing the UIAccelerometer in Iphone and iPad

May 30, 2011 by Krishna Srinivasan Leave a Comment

This article is based on iPhone and iPad in Action, published on August, 2010. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) eBooks and pBooks. MEAPs are sold exclusively through Manning.com. All pBook purchases include free PDF, mobi and epub. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information. [ Use promotional code ‘java40beat’ and get 40% discount on eBooks and pBooks ]

Accessing the UIAccelerometer

Introduction

When you’re using the iPhone’s orientation notification, the frameworks are doing the work for you: they’re taking low-level acceleration reports and turning them into more meaningful events. It’s similar to the concept of iPhone actions, which turn low-level touch events into high-level control events.

Notifications aren’t going to be sufficient if you would prefer to program entire interfaces that effectively use the iPhone’s movement in three-dimensional space as a new user-input device. For that, you’ll need to access two iPhone classes: UIAccelerometer and UIAcceleration. We’ll talk about UIAccelerometer.

The UIAccelerometer is a class that you can use to receive acceleration-related data. It is a shared object, like UIApplication and UIDevice. The process of using it is shown in listing 1.

Listing 1 Accessing the UIAccelerometer takes just a few steps
[code]- (void)viewDidLoad {
UIAccelerometer *myAccel =
#1
[UIAccelerometer sharedAccelerometer]; #1
myAccel.updateInterval = .1; #2
myAccel.delegate = self; #3
[super viewDidLoad];
}
#1 Creates shared accelerometer
#2 Updates 10 times a second
#3 Delegates accelerometer protocol[/code]
The first step is to access the accelerometer, which is done with another call to a shared-object method (#1). Having this step on its own line is probably unnecessary, because you could perform the other two steps as nested calls, but we find this a lot more readable.

Next, you select your update interval (#2), which specifies how often you’ll receive information on acceleration. This is hardware limited, with a current default of 100 updates per second. That’s most likely just right if you’re creating a game using the accelerometer, but excessive for other purposes. We’ve opted for 10 updates per second, which is an updateInterval of 0.1. You should always set the lowest acceptable input to preserve power on the iPhone.

Finally, you must set a delegate for the accelerometer (#3), which is how you receive data on accelerometer changes. The delegate will need to respond to only one method, accelerometer:didAccelerate:, which sends a message containing a UIAcceleration object whenever acceleration occurs (to the limit of the updateInterval).

Summary

The iPhone’s accelerometers can give you access to a variety of information about where an iPhone exists in space. By measuring gravity, you can easily discover an iPhone’s precise orientation. By measuring movement, you can see how an iPhone is being guided through space. Finally, you can build more complex movements into three-dimensional gestures, such as the shake.

Accelerometers allow users to make simple adjustments to a program. We can imagine game controls and painting programs both built entirely around the accelerometers.

Filed Under: Apple Tagged With: iPad, iPhone

Adding a map to an application in iPhone and iPad

May 30, 2011 by Krishna Srinivasan Leave a Comment

This article is based on iPhone and iPad in Action, published on August, 2010. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) eBooks and pBooks. MEAPs are sold exclusively through Manning.com. All pBook purchases include free PDF, mobi and epub. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information. [ Use promotional code ‘java40beat’ and get 40% discount on eBooks and pBooks ]

Adding a map to an application

Introduction

Adding a map to any application is very similar to adding any other view. You can either do it through Interface Builder or programmatically. The choice is up to you depending on how you like to work with UI elements. We will show you both methods.

The view that displays a map is called MKMapView. This class contains quite a bit of functionality including how to display the map, annotations, and user location. We will first be discussing how to add an MKMapView through Interface Builder. Once we add the map to the view, we will connect it to an IBOutlet and set its delegate class.

Adding the map using Interface Builder

Before you start coding the MKMapView, you must first import MapKit.framework. This will provide you will all of the libraries needed to work with maps.

To add a map to your view, your must first create an MKMapView IBOutlet in the class that will be using the map. Listing 1 shows how to do this.

Listing 1 Declaring an IBOutlet for an MKMapView
[code]#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
@interface SimpleMapViewController : UIViewController<MKMapViewDelegate> {
IBOutlet MKMapView * theMap;
}[/code]
@property (nonatomic, retain) IBOutlet MKMapView * theMap;
The first thing we want to point out is you must import the MapKit.h header file. This is included in MapKit.framework and is needed for all MapKit interaction. The second is, our class implements the MKMapViewDelegate interface. It will allow this class to become the delegate of the MKMapView and receive messages from it. In addition to making a property, you should also synthesize the map property in the .m file.

Now that the IBOutlet has been declared, you need to add the MKMapView to the view in the nib file. To do this open up the nib file associated with the class that contains your IBOutlet. Now, select MKMapView from the Library and drag it on to your view. Figure 1 shows what this object should look like.

Figure 1 Adding an MKMapView to your viewWhen you drag the map on to you view, you are able to move and resize it however you like. Now that it has been added, you must connect it to the IBOutlet. To do this, click on the File’s Owner object and open the Connections Inspector. Now, drag from the map outlet to the map view to make the connection.

The last thing that needs to be done is set the delegate of the MKMapView. To do this, right click on the map and drag to the File’s Owner object. It should pop up a bubble that reads, “delegate”. Click the word delegate to make the connection. Figure 2 shows what the Connection Inspector should look like after you have completed all of these steps.

Figure 2 Connection inspector for the MKMapView connectionsAs you can see, adding an MKMapView using Interface Building is about the same as adding UILabels, UITextFields, and other view elements. Now that you have seen how to add the map visually, we will show you how to add one programmatically.

Adding the map programmatically

As noted before, whether you add the map using Interface Builder or with code is up to you. It is completely dependent on your preferences and organization technique. Listing 2 demonstrates how to add an MKMapView to your view controller’s view using code.

Listing 2 Adding an MKMapView programmatically
[code]- (void)viewDidLoad {
[super viewDidLoad];
MKMapView * map = [[MKMapView alloc] initWithFrame:
CGRectMake(0, 0, 320, 480)];
Map.delegate = self;
[self.view addSubview:map];
}[/code]
This code is actually quite short. We create the map using a frame, set its delegate to our class, and add it to our class’ view. As with any other view, modifying the frame passed to the map will alter its size and position.

Controlling the map

By default, the map has gives the user a bit of control. Without any additional code, they have the ability to scroll all over the world by flicking the map. Also, the map comes with the ability to zoom in and out by using the pinch and pull gestures.

To navigate the map programmatically, you must specify a region. Doing this will allow you to move the map to a specified location. You will also have the ability to set the zoom level.

Let’s examine the region properties and methods for navigating the map. Table 1 discusses these properties and methods and their uses.

The code below shows you how to create an MKCoordinateRegion and move the map to display it on the screen. The method we created here fires when a user presses a button titled Apple. It will move the map from its current location to center on Apple’s headquarters in Cupertino.

Listing 3 moving the map to a given location
[code]- (IBAction) apple:(id) sender {
CLLocationCoordinate2D coords;
coords.latitude = 37.33188;
coords.longitude = -122.029497;
MKCoordinateSpan span = MKCoordinateSpanMake(0.002389, 0.005681);
MKCoordinateRegion region = MKCoordinateRegionMake(coords, span);
[theMap setRegion:region animated:YES];
}[/code]
The first thing we see here is a CLLocationCoordinate2D being created. This is simply a struct that holds two doubles for latitude and longitude. Next, we assign them to the coordinates of Apple using the WGS 84 reference frame.

Following the coordinates, we create a span using the MKCoordinateSpanMake method. An MKCoordinateSpan is a struct made of two doubles that represent a delta for latitude and longitude. The span represents the amount of area to view and is used when setting the zoom level. A larger number here tells the map to show a larger view area resulting in the map zooming out. Similarly, a smaller number tells the map to show less area and causes it to zoom in.

Once the coordinates and span have been initialized, we can create a region using the MKCoordinateRegionMake method. Finally, we set the region of the map to our newly created one and animate the transition. In addition to controlling the map’s location, you can also control how the user can interact with it. Table 2 details these properties.

As mentioned above, the mapType property allows you to display the map in three different ways. Most likely, you will want to make this configurable by the user, as preferences tend to vary about how the map should display. Figure 3 shows the difference between the map types.

Figure 3 mapTypes: (from left to right) MKMapTypeStandard, MKMapTypeSattelite, MKMapTypeHybridAs you can see, you have quite a bit of control over how the map looks. The standard map view looks very much like a road map that you would use for navigation. This is often the most useful of the map types.

The other two are quite similar. The only difference between them is the hybrid view contains the road names in addition to displaying the satellite photos.

Filed Under: Apple Tagged With: iPad

Preparing your application to use push notifications in iPhone and iPad

May 30, 2011 by Krishna Srinivasan Leave a Comment

This article is based on iPhone and iPad in Action, published on August, 2010. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) eBooks and pBooks. MEAPs are sold exclusively through Manning.com. All pBook purchases include free PDF, mobi and epub. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information. [ Use promotional code ‘java40beat’ and get 40% discount on eBooks and pBooks ]

Preparing your application to use push notifications

Introduction

Leave it to Apple to make the preparation more complex than the coding. You will find that more time is spent on creating an uploading the signing certificates than actually writing the code to receive the push notifications. We will explain how. Let’s begin by setting up the signing certificates.

Setting up your application certificate

The first thing to note is that you must have a valid Apple developer account to test push notifications. We will be showing you how to generate two items that are required. The first item we will be generating is a special provisioning profile. This profile will be used to sign the application when deploying it to your iPhone. The second is a client SSL certificate. The push provider will use this to establish a connection with Apple’s push notification servers.

Start by logging into your Apple developer account. Once you have logged in, open up the program portal and navigate to the App IDs tab. If you haven’t already done so, you will need to add your application bundle identifier to this list. The format for this should be reverse domain. An example of this might be com.rightsprite.pushtest. Make sure that you don’t use any wildcards because the system must be able to uniquely identify your application.

Once you have added your application, you must now configure it to receive push notifications. You have the option to configure the app for development as well as production. It is always good practice to use the development certificate when testing and switch to the production one when you are ready to submit to the app store. Figure 1 shows what this section should look like.

Figure 1 Configuring the app to receive push notificationsAfter pressing the Configure button, the following screen gives you the option to configure either the development or the production certificate. For this example, we will be configuring the debug certificate; however, the steps for both are exactly the same. Figure 2 shows what this process looks like.

Figure 2 The wizard for creating a push certificateClicking Configure will open up a wizard with steps that will guide you through the process. This process is very similar to creating any other provisioning profile. After completing this step, you need to download this certificate and install it in your keychain by double-clicking on it.

Setting up you provisioning profile

Now that we have created the signing certificate, we will need to create the provisioning profile to allow the application to be installed on your iPhone. Again, you don’t want to use your generic developer certificate. You must generate a new one that is specific to your app’s full bundle id.

Go to the Provisioning tab. Since we created a push certificate for debug, we must also create a debug provisioning profile. Had we created a production certificate, you would need to create an app store or adhoc certificate. Click on the New Profile button within the Development tab.

As you may have seen before, there are quite a few options that need to be set up. The first is the profile name. This can be anything you want; however, your best bet is to be very descriptive. Name it something like [Application Name] Debug. Next, you will select the certificate that the profile will be using.

If you are a single user, you should only see your certificate in the list. However, if you are on a team, you should see a certificate for every one of your team members. Just check the boxes of the teammates that will be testing the push notifications. Note that when creating a build for the app store, you will select your distribution certificate.

Following the certificate, you will need to select the app id that the profile will be used for. Finally, you must select the devices that the provisioning profile will work on. Figure 3 shows an example of what this form looks like completed.

Figure 3 Provisioning profile formAfter creating this profile, you will need to download and install it. That is about it for the certificate creation. We will now be discussing how to implement the methods in your client application to enable and receive push notifications.

The code for handling push notifications

As we mentioned earlier, the code to handle push notifications is quite simple. In fact, there are only three methods that need to be implemented. We will be walking through each of these methods and discussing their use.

The first method is the applicationDidFinishLaunching method. This method is already implemented for you in any application that you create. You simply need to add one line of code that will tell your application to register for push notifications. The following code shows you how to do this.
[code]- (void)applicationDidFinishLaunching:(UIApplication *)app {
[[UIApplication sharedApplication]
registerForRemoteNotificationTypes:( UIRemoteNotificationTypeAlert
|UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
}[/code]
Your application will have other setup tasks in this method; we just wanted to show you the line of code that must be added to register for push notifications. The code above will tell the device that this application wants to receive push notifications in the form of alerts, badge numbers, and sounds. You can omit any of these properties if you choose not to send them.

One thing you might be wondering is why this must be done more than once. The reason for this is the token that gets generated when setting up push notifications is not guaranteed to be the same. So, we want to touch base with Apple every time the application launches to make sure everything is correct to receive notifications.

As you may have guessed, there are some delegate methods that must be implemented to react to events generated by this registration call. The code below shows a simple implementation of these methods.
[code]didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {
[self sendProviderDeviceToken: devToken];
}
– (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
NSLog(@"Error in registration. Error: %@", err);
}[/code]
The first method fires upon successful registration for push notifications. When you register to receive push notifications, your application communicates with Apple and receives back a unique device token. This token is used in all push communication with your device.

Notice we call a method sendProviderDeviceToken in our class. This is a custom method you should create to send the device token to your push provider. You may do this via a web service interaction.

The method didFailToRegisterForRemoteNotificationsWithError is for error handling. It fires when you get an error registering for push notifications. Most likely, if this method gets called, your signing certificate is invalid or the device doesn’t have an Internet connection. Make sure you put some code in this method to notify the user that there was a problem registering for notifications and they will not receive any at this point.

Now that the application has registered to receive push notifications, the next step is to handle them when they come in. Apple gives us a few methods that will allow us to control what happens when the user presses the View button on the notification alert.

The first way of handling an incoming push notification is to simply implement the code in the applicationDidFinishLaunching method. You would want to go this route if the notification was just used to open the application and did not pass any additional data. The following code shows a simple way to respond.
[code]
– (void)applicationDidFinishLaunching:(UIApplication *)application {
application.applicationIconBadgeNumber = 0;
[self getUpdatedDataFromServer];
}[/code]
The first and most important thing you must do here is reset the badge number to 0. If you don’t do this, the badge count will stay at whatever number was sent by the push notification. After that, you should perform any updates that are needed. In the above code, we assume that some data has changed on the server and call a method to download the updated data.

If the notification contains a custom dictionary, you must use the application:didFinishLaunchingWithOptions: method. The options variable will be an NSDictionary containing the custom values passed in.

In the event that the user is currently running the application, you must implement the application:didReceiveRemoteNotification: method. It will be called automatically and passed a dictionary containing all of the standard information including badge number, message, sound, and any custom dictionaries that were sent to the device.

After implementing the aforementioned methods, your application should now be ready to receive push notifications. One final step in preparation is to format any audio files that will be played in response to a push notification.

Preparing audio files

As noted before, when a push notification is received, it can invoke the playback of an audio file included with your application. There are many interesting scenarios for when different audio files might be appropriate. One example might be during a chess match. If a player receives a notification informing them it’s their turn, the system might simply play the default audio file. However, if they receive a notification related to a piece being captured, the system might play some sort of battle sound effects. The more creative you get with this, the more value it may add to your application.

The first thing to note when considering the audio file to play is that the file must be stored in your application’s main bundle directory. This is just the root folder that your applications files are stored in. Your audio file must be in the format of aiff, wav, or caf and limited to 30 seconds. In order to convert the audio file to one of these formats, you must use the afconvert command on you Mac. To do this, open the Terminal and navigate to the directory of the audio file you wish to convert. Next, type the afconvert command followed by -f caff -d LEI16 {INPUT} {OUTPUT}. The following shows an example of using this command to convert the file track2.mp3 to track2.caf.
[code]/usr/bin/afconvert -f caff -d LEI16 track2.mp3 track2.caf[/code]
For corresponding display in the terminal, see figure 4.

Figure 4 Converting audio files in the terminalYou will need to do this for every sound file that you wish to invoke from a push notification.

Summary

As we have seen, push notifications offer a very simple solution to a complex problem. They give developers the ability to mimic the functionality of running their application in the background while conserving the system resources on the iPhone.

Apple has provided us with a very robust service that we are able to use free of charge. This service is the centerpiece of the entire push notification system and allows us to send simple messages from a provider to a specific iPhone with very little delay.

In order to receive the push notifications, applications must be prepared and signed with a special signing certificate generated on Apple’s website. You must create a signing certificate for use in development mode as well as debug mode when testing push notifications in your application. This certificate is used in conjunction with your private key to create the SSL certificate needed to communicate with Apple’s servers.

Filed Under: Apple Tagged With: iPad, iPhone

Simple Accelerometer Movement in iOS4

May 29, 2011 by Krishna Srinivasan Leave a Comment

This article is based on iOS 4 in Action, to be published on June 2011. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) eBooks and pBooks. MEAPs are sold exclusively through Manning.com. All pBook purchases include free PDF, mobi and epub. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information. [ Use promotional code ‘java40beat’ and get 40% discount on eBooks and pBooks ]

Recognizing Simple Accelerometer Movement

Introduction

If you want to write programs using acceleration gestures, we suggest that you download the Accelerometer Graph program available from Apple’s developer site. This is a nice, simple example of accelerometer use; but more important, it also provides you with a clear display of what the accelerometers report as you make different gestures. Make sure you enable the high-pass filter to get the clearest results.

Figure 1 shows what the Accelerometer Graph looks like in use (but without movement occurring). As you move the device around, you’ll quickly come to see how the accelerometers respond.

Figure 1 The Accelerometer Graph shows movement in all three directions.Here are some details you’ll notice about how the accelerometers report information when you look at the Accelerometer Graph:

  • Most gestures cause all three accelerometers to report force; the largest force should usually be on the axisof main movement.
  • Even though there’s usually a compensating stop force, the start force is typically larger and shows the direction of main movement.
  • Casual movement usually results in forces of .1 g to .5 g.
  • Slightly forceful movement usually tops out at 1 g.
  • A shake or other more forceful action usually results in a 2 g force.
  • The accelerometers can show things other than simple movement. For example, when you’re walking with an iPhone or iPad, you can see the rhythm of your pace in the accelerometers.

All of this suggests a simple methodology for detecting basic accelerometer movement: you monitor the accelerometer over the course of movement, saving the largest acceleration in each direction. When the movement has ended, you can report the largest acceleration as the direction of movement.

Listing 1 puts these lessons together in a program that could easily be used to report the direction of the device’s movement (which you could then use to take some action).

Listing 1 Movement reporter that could be applied as a program controller
[code]- (void)accelerometer:(UIAccelerometer *)accelerometer
didAccelerate:(UIAcceleration *)acceleration {
accelX = ((acceleration.x * kFilteringFactor) #1
+ (accelX * (1 – kFilteringFactor))); #1
accelY = ((acceleration.y * kFilteringFactor) #1
+ (accelY * (1 – kFilteringFactor))); #1
accelZ = ((acceleration.z * kFilteringFactor) #1
+ (accelZ * (1 – kFilteringFactor))); #1
float moveX = acceleration.x – accelX; #2
float moveY = acceleration.y – accelY; #2
float moveZ = acceleration.z – accelZ; #2
if (!starttime) { #3
starttime = acceleration.timestamp; #3
} #3
if (acceleration.timestamp > starttime + 1 &&
(fabs(moveX) >= .3 ||
fabs(moveY) >= .3 ||
fabs(moveZ) >= .3)) {
if (fabs(moveX) > fabs(moveVector)) {
moveVector = moveX; #4
moveDir = (moveVector > 0 ? @"Right" : @"Left");
}
if (fabs(moveY) > fabs(moveVector)) {
moveVector = moveY; #4
moveDir = (moveVector > 0 ? @"Up" : @"Down");
}
if (fabs(moveZ) > fabs(moveVector)) {
moveVector = moveZ; #4
moveDir = (moveVector > 0 ? @"Forward" : @"Back");
}
lasttime = acceleration.timestamp;
} else if (moveVector && acceleration.timestamp
> lasttime + .1) {
myReport.text =
[moveDir stringByAppendingFormat:
@": %f.",moveVector];
moveDir = [NSString string];
moveVector = 0;
}
}
#1 Gathers filtered info
#2 Measures movement
#3 Marks start time
#4 Saves largest movements[/code]
You start by creating a low-pass filter (#1) and then taking the inverse of it (#2) in order to get relatively clean movement data. Because the data can be a little dirty at the start, you don’t accept any acceleration data sent in the first second (#3). You could cut this down to a mere fraction of a second.

You start looking for movement whenever one of the accelerometers goes above .3 g. When that occurs, you save the direction of highest movement (#4) and keep measuring it until movement drops below .3 g. Afterwards, you make sure that at least a tenth of a second has passed so that you know you’re not in a lull during a movement.

Finally, you do whatever you want to do with your movement data. This example reports the information in a label, but you’d doubtless do something much more intricate in a live program. Cleanup is required to get the next iteration of movement reporting going.

This sample program works well, unless the movement is very subtle. In those cases, it occasionally reports the opposite direction because of the force when the device stops its motion. If this type of subtlety is a problem for your application, more work is required. To resolve this, you need to make a better comparison of the start and stop forces for movements; if they’re similar in magnitude, you’ll usually want to use the first force measured, not necessarily the biggest one. But for the majority of cases, the code in listing 1 is sufficient. You now have an application that can accurately report (and take action based on) direction of movement.

Together, gravity and force measurement represent the most obvious things that you can do with the accelerometers, but they’re by no means the only things. We suspect that using the accelerometers to measure three-dimensional gestures will be one of their best (and most frequent) uses as the platform matures.

Summary

Accelerometers can give you access to a variety of information about where a device exists in space. By sensing gravity, you can easily discover precise orientation. By measuring movement, you can see how the device is being guided through space.

Filed Under: Apple Tagged With: iOS

Event Kit Frameworks in iOS4

May 29, 2011 by Krishna Srinivasan Leave a Comment

This article is based on iOS 4 in Action, to be published on June 2011. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) eBooks and pBooks. MEAPs are sold exclusively through Manning.com. All pBook purchases include free PDF, mobi and epub. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information. [ Use promotional code ‘java40beat’ and get 40% discount on eBooks and pBooks ]

An Overview of the Event Kit Frameworks

Introduction

Calendar apps coming with iOS on iPhone and iPad are really convenient for several reasons. They allow users to check out the schedule on the go and consolidate all the information into one Calendar database.

Figure 1 Calendar app on iPhone and iPadIn order to access the Calendar database, Apple provides the convenient API in iOS 4 with event kit. There are two frameworks for the Event Kit, as we mentioned earlier. Event Kit framework gives you the access to insert and delete an event in the Calendar’s database. It’s a high-level API access to the calendar database and the best part is that any changes made to the calendar will be synced automatically, so you can have a peaceful mind when you are writing the code for calendar access. Event Kit UI framework provides the handy interfaces to display and edit Calendar’s database with the same view controller you’ve already used with the Calendar app on the iPhone or iPad.

Adding Event Kit frameworks to your project

In order to use the Event Kit frameworks, we first need to add the existing Frameworks EventKit.framework and EventKitUI.framework to the project. Head over to Xcode, right-click on the folder Frameworks on left panel, choose Add>Existing Frameworks…; you should be able to see the whole list of available frameworks under current SDK, as shown in figure 2. Navigate to EventKit.framework and click on button Add. You will see a new framework added to your project. Repeat the same process for the Event Kit UI framework.

Figure 2 Add the Event Kit framework from the project panel.After adding the required frameworks to the project, you also need to include two files to the header file you wish to use, as below:

  • #import <EventKit/EventKit.h>
  • #import <EventKitUI/EventKitUI.h>

With the Event Kit frameworks added to the project, you can start to use them for accessing Calendar’s database from the application. First, we will take a look at the Event Kit Classes.

Event Kit Classes

Inside the powerful Event Kit API, there are a handful of classes that are like a lot of useful friends; figure 3 gives you a general idea about the relationships among these important classes.

Figure 3 The Event Kit Classes structureAs you can see from figure 3, EKEventStore is the key object here and it’s the connection to the calendar database. You can use the code snippet below to initialize an EKEventStore object for calendar data access.
[code]EKEventStore *store = [[EKEventStore alloc] init];[/code]
Please note that this initial method may consume a lot of time, so it’s a good practice to keep that EKEventStore object in your program around for all the data access.

EKEvent is the object representing an event, which includes some import properties listed in table 1.

After the EKEventStore object is initialized, the calendar’s ready for adding or deleting events. You can create an event object and add it to the calendar’s database programmatically. Alternatively, you can use Event Kit UI framework for event view controllers, which is a great choice for user interface. The Event Kit UI framework contains two types of view controllers for manipulating events:

  • EKEventViewController—Use the EKEventViewController class if you have an existing event you want to display or allow the user to edit.
  • EKEventEditViewController—Use the EKEventEditViewController class if you allow the user to create, edit, or delete events.

Summary

The Event Kit framework provides an interface for accessing calendar events on a user’s device. You can use this framework to get existing events and add new events to the user’s calendar. In this article, you learned how to accomplish this task with the Event Kit UI view controllers.

Filed Under: Apple Tagged With: iOS

Multitasking on iOS 4

May 29, 2011 by Krishna Srinivasan Leave a Comment

This article is based on iOS 4 in Action, to be published on June 2011. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) eBooks and pBooks. MEAPs are sold exclusively through Manning.com. All pBook purchases include free PDF, mobi and epub. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information. [ Use promotional code ‘java40beat’ and get 40% discount on eBooks and pBooks ]

Introduction

What’s multitasking? It’s one of the important and exciting API features in iOS 4. When the end user quits an application, instead of termination, the application will enter the background state so that we can use this feature to support fast app switching, running tasks in the background. In this article, we will take a look at the basics of multitasking on iOS 4 and the applications life cycle.

Overview

Multitasking is a key feature that has been requested on the iOS since it was first released. It’s basically the ability to let the device run more than one application at once. For example, you may want to listen to music using the Pandora application while performing other tasks such as checking your email.

In the past, Apple had a few arguments opposed to multitasking on the iOS; the primary one was that it slows down the device and makes for an overall poor user experience. If you allow the user to run too many applications at once, the device will eventually run out of memory and start killing those applications. Another argument was that running many applications at the same time drains battery life much more quickly. Because running an app requires processing power, the constant strain on the processor will quickly result in a drained battery.

Finally, in iOS 4, Apple has implemented the ability for programs to run in the background. Figure 1 shows the multitasking UI on iPhone and iPad. This isn’t true multitasking per se, but it’s getting closer and addresses most of users’ other gripes.

Figure 1 Multitasking UI on iPad and iPhoneApplications that wish to execute operations in the background are restricted to certain tasks, which include the following:

  • Requesting a set amount of time to finish a task.
  • Implementing specific services allowed by Apple, including location tracking, audio playback, and voice over IP services.

By default, all applications that are compiled for iOS 4 will support multitasking. But after the user taps the home button, the app will go into the background suspended state unless the background running mode is added.

Because most applications don’t require constant usage, the system automatically puts them in a suspended state when the user exits them. Upon resuming the application, it should load in the last state it was in when the user exited it. This is more of a fast application-switching model. A great comparison is when you are reading a book, you may want to take a break and get a cup of coffee, so you will put a bookmark at the page you stopped. Later when you are back, you can continue from the exact same page where you left.

Application life cycle

With the iOS multitasking support, the application life cycle expands to not running, running in the foreground and running in the background (as shown in figure 2).

Figure 2 Application life cycle in iOS 4When the application first launches, it will move from the not running state to the foreground, stay inactive briefly, and become active. That’s the time when the MainWindow.xib file gets loaded into the application. While the application is running in the foreground state, an SMS message or an incoming call could pop out and interrupt the current application, which, therefore, will become inactive.

When the user presses the Home button, the application will move from the foreground state to the background. The application may continue running if the background mode is supported on the device (in other words, iPhone 3G and iPod Touch 2nd Gen won’t support the background state at all), such as the background audio. When a user is listening to their iPod and pushes the Home button, the application still plays music in the background state.

Most applications will stay in the suspended state after moving to background mode and won’t execute code in the suspended state. When the user switches back to this application after some time, it will automatically return from the background to the foreground state, where it was left last time.

Sometimes, when the system is running low on memory, the heavy memory usage applications in the background will get terminated in order to free up more memory for the foreground application. Another possibility is when the user manually terminates the application from the multitasking UI stack.

In iOS 4, it’s really important to understand the application’s life cycle in order to design a responsive and smooth transition application. For example, when you are designing a game application, you want to pause the game when there is an incoming call and save the important data before the application quits or moves to the background state. How can you monitor the application’s life cycle during the run time?

There are two solutions available on iOS 4. One solution is to respond to each major callback method in the application delegate. Another way is to observe the notifications from the notification center. Table 1 has a complete side-by-side list of application delegate methods and notifications.

Inside the application’s delegate, you can monitor the application’s life cycle state and transitions; at the time of writing, there are 6 major callbacks available in the application delegate:

  • application:didFinishLaunchingWithOptions:—This is the most important method and has been used in the entire book. This method can be used to initialize the application and prepare it for running in the foreground state, such as loading the Main Window nib file.
  • applicationDidEnterBackground:—It’s the key callback method to prepare the application for the background state. Use this method to release shared resources, save user data, invalidate timers, and store enough application state information in order to restore your application to its current state. If the application supports background execution, this method will get called instead of applicationWillTerminate when the user taps the home button.
  • applicationWillEnterForeground:—This method is sent when the application resumes from the background state and will enter into foreground. You can use this method to restore the application and undo the changes before the application enters the background. For example, the application can load the resources and restore the data.
  • applicationDidBecomeActive:—This method can be used to customize the application behavior when the application becomes active in the foreground. For example, it will be called when the interruption is gone. Or when the application continues transition from inactive state to active state after the method applicationWillEnterForeground gets called. Use this task to restart the tasks paused before. For example, you should continue the game, restart the timer, and update the user interface.
  • applicationWillResignActive:—This method gets called when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it’s about to start the transition to the background state. You can use this method to pause ongoing tasks, disable timers, and tune down OpenGL ES usage.
  • applicationWillTerminate:—This method is called when the application is about to get terminated. The application will transit back to the not running state.

In order to monitor the application’s transition states with the notification center, table 1 has a complete list of notifications. For example, you can use the code snippet below to register a notification for UIApplicationWillResignActiveNotification inside the view controllers.
[code]NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
[notifCenter addObserver:self selector:@selector(resignActive:) name:UIApplicationWillResignActiveNotification object:nil];[/code]
As you can tell, in order to support the multitasking smoothly in the application, you need to consider saving the application’s data properly before the application moves to the background, and reload the necessary data before the application launches from the background mode.

Summary

Multitasking is really useful in so many ways. With the application continues running in the background, you can provide an amazing user experience with the iOS 4’s platform. We covered the multitasking basics and the application’s life cycle on iOS 4.

Filed Under: Apple Tagged With: iOS

Using an alert view as a task loader in iPad

May 26, 2011 by Krishna Srinivasan Leave a Comment

This article is based on iPad in Practice, to be published on Summer 2011. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) eBooks and pBooks. MEAPs are sold exclusively through Manning.com. All pBook purchases include free PDF, mobi and epub. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information. [ Use promotional code ‘java40beat’ and get 40% discount on eBooks and pBooks ]

Using an alert view as a task loader

Introduction

Some actions, like signing out of an account in an application, require a user to both confirm the action and to indicate the processing of the action. When you need to present this type of flow to a user, an interesting option is to present an alert with a confirm/cancel option and then to use the alert as a loader while the action is being processed.

Problem

Providing a loader during different types of operations can be a very valuable user interaction technique. One approach to doing so is by providing a loader as part of an alert view interaction.

Solution

Our app is going have one view with a button to fire the alert interaction. When the user taps the button, we display an alert that gives them the choice to sign out of the application. If they tap the action button, we display a loader and process the action. Once the action is completed, we display a second alert view that confirms the completion of the action.

Start by creating a new project. Call it AlertLoader and select a view-based project as the project type. Click on the AlerLoaderViewController.h header file as in listing 1 to start setting up the view controller.

Listing 1 AlertLoaderViewController.h header
[code]#import
@interface AlertLoaderViewController : UIViewController {
UIAlertView *alertView;
}
@property(nonatomic, retain) UIAlertView *alertView; #1
– (IBAction) signout; #2
– (void) runProcess; #2
– (void) showAlertLoader; #2
@end

#1 UIAlertView property
#2 Function and action declarations[/code]
In the header file, we define a single property (#1), which is a UIAlertView. This is the alert view we’ll be using to control our interaction and to display the loader. We also declare three functions (#2) on IBAction, which will be attached to our button to start the interaction. The other two we’ll review in the implementation of the controller. Edit your header file to implement the property and function declarations.

Now double-click on the AlertLoaderViewController.xib to modify the UI in the interface builder. Your view will be pretty much empty; all you need to do is drag a single UIButton on the view and give it the title Sign Out. Now, connect the button to the IBAction signout on the controller as shown in figure 1.

The core of the solution is in the implementation of the controller where we implement the alert interactions. Let’s take a look at that next in listing 2.

Listing 2 AlertLoaderViewController.m implementation
[code]#import "AlertLoaderViewController.h"
#define START_RUNNING_INDEX 1
#define PROCESS_LOADING_TAG 200
#define PROCESS_LABEL_TAG 201
@implementation AlertLoaderViewController
@synthesize alertView;
#pragma mark –
#pragma mark AlertView Delegate methods
(void)alertView:(UIAlertView *)alertView #1
clickedButtonAtIndex:(NSInteger)buttonIndex { #1
if(START_RUNNING_INDEX == buttonIndex) #1
[self runProcess]; #1
}
#pragma mark –
#pragma mark Sync now
– (IBAction) signout { #2
NSLog(@"sync now"); #2
self.alertView = [[[UIAlertView alloc] #2
initWithTitle:@"Sign Out" #2
message:@"Sign Out" #2
delegate:self #2
cancelButtonTitle:@"Cancel" #2
otherButtonTitles:@"Confirm", nil] autorelease]; #2
UIActivityIndicatorView *loading = #2
[[UIActivityIndicatorView alloc] #2
initWithActivityIndicatorStyle: #2
UIActivityIndicatorViewStyleWhiteLarge]; #2
loading.frame = CGRectMake(122.0, 40.0, #2
loading.frame.size.width, #2
loading.frame.size.width); #2
loading.tag = PROCESS_LOADING_TAG; #2
[loading stopAnimating]; #2
[alertView addSubview:loading]; #2
[loading release]; #2
[alertView show]; #2
} #2
– (void) showAlertLoader { #3
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; #3
[(UIActivityIndicatorView *) #3
[self.alertView viewWithTag:PROCESS_LOADING_TAG] #3
startAnimating]; #3
[(UILabel *)[self.alertView viewWithTag:PROCESS_LABEL_TAG] #3
setHidden:NO]; #3
self.alertView.title = @"Processing…"; #3
self.alertView.message = @""; #3
[pool release]; #3
} #3
#pragma mark –
– (void) runProcess { #4
[NSThread detachNewThreadSelector:@selector(showAlertLoader) #4
toTarget:self #4
withObject:nil]; #4
[NSThread sleepForTimeInterval:10]; #4
UIAlertView *alert = [[[UIAlertView alloc] #4
initWithTitle:@"Completed" #4
message:@"Sign out completed" #4
delegate:nil #4
cancelButtonTitle:@"OK" #4
otherButtonTitles:nil] autorelease]; #4
[alert show]; #4
} #4
– (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
– (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
– (void)dealloc {
[alertView release];
[super dealloc];
}
@end
#1 Alert view delegate function
#2 Display alert and init loader
#3 Display the loader
#4 runProcess our fake worker function[/code]
The AlertLoaderViewController first implements the UIAlertView delegate protocol at #1 by implementing alertView:clickedButtonAtIndex: function, which is called when an alert view button is tapped. In this case, we have a constant START_RUNNING_INDEX, which is used to match the action button index for our main alert view.

At #2, we implement the signout IBAction, which is responsible for displaying the choice alert view to our user. When we create the alert view we also create a UIActivityIndicatorView, which will be our loader, set its frame, and add it as a subview to the alert view. You’ll notice that we call stopAnimating on the activity indicator. The default behavior of the activity indicator is to hide itself when it is not animation. So, we call stopAnimating when we add it and then later call startAnimating to display it. When signout is called, we get the alert view pictured in figure 2.

The showAlertLoader (#3) and runProcess (#4) functions work together. runProcess is actually what is called by our alert view delegate function when the user taps Confirm in the Sign Out alert. The runProcess function first fires off a call to showAlertLoader in the background using detachNewThreadSelector:toTarget:withObject:, which modifies the displayed loader to show our activity indicator, as depicted in figure 3.

Finally, in #4, after the loader has been displayed, we do our fake work. In this case, we just call sleepForTimeInterval: to pause the thread for 10 seconds as a simulation of doing some other work. Once the sleep completes, we create and show a new alert view to inform the user that the process has completed.

Discussion

Looking at this technique, we can see that it’s fairly simple; all it really does is add a subview to an alert view as a means of smoothing out some user interaction flow. It’s worth noting that this isn’t something to take too lightly. Adding a subview to a system view is accepted by Apple and I’ve used this approach in a few different applications in cases where it made sense. However, you need to be aware that trying to use private properties or views of a system view is a different story. I’ve heard it directly from Apple engineers that they not only frown upon trying to access and manipulate private components but that they are going to be checking for this and rejecting apps based on it. This particular technique doesn’t try to use or change the original UIAlertView other than clearing the text of the detail label, but going any farther may be walking a fine line with the app review team.

As shown in figure 4, after our loader has completed we show a confirmation loader, this is an optional extra piece of information you can show the user.

Summary

Alerts are a simple view, which was carried over from the iPhone SDK they give you a way to notify users of changes in state. You should try to use Alerts only in cases where it is really necessary to notify the user of a change that will impact their use of the application. Alerts views are extremely simple but can be very effective so it is a good idea to be familiar with how to use them.

We showed you how to set up one view with a button to fire the alert interaction so that, when the user taps the button, we display an alert that gives them the choice to sign out of the application. Tapping on the action button displayed a loader and processed the action at the same time. Once the action was completed, we displayed a second alert view that confirmed the completion of the action.

Filed Under: Apple Tagged With: iPad

Follow Us

  • Facebook
  • Pinterest

As a participant in the Amazon Services LLC Associates Program, this site may earn from qualifying purchases. We may also earn commissions on purchases from other retail websites.

JavaBeat

FEATURED TUTORIALS

Answered: Using Java to Convert Int to String

What is new in Java 6.0 Collections API?

The Java 6.0 Compiler API

Copyright © by JavaBeat · All rights reserved