
There are many kinds of alert views that you can utilise within Apple’s UIKit, the most obvious being UIAlertView. However there are also UIActionSheets and the undocumented UIProgressHUD, the pretty Volume like HUD that you see on mac that apple use within their own iPhone applications. It’s there for you to use, however do be warned if not used correctly apple WILL not let your app onto the AppStore as this is a Private API.
UIAlertView, iPhones typical alert view.
UIAlertView is used throughout the iPhone OS for things such as text messages (SMS) and Push Notifications.
Implementing UIAlertView is extremely simple and handling button taps is done through a delegate method. For more information on handling button taps with the UIAlertView delegate method please refer to the demonstration project attached to this article.
Firstly we allocate and initialise a UIAlertView object.
message:@"This is a UIAlertView, subclass of UIView."
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Do Somthing", nil];
The method used for initialisation in most cases is - (id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, … This method will create the UIAlertView with the given parameters and allocate the object memory until it’s released.
To display the UIAlertView we simply call the show method, once this method has been called you can go ahead and release the UIAlertView object.
[myAlert release];
This UIAlertView object will display the UIAlertView buttons in a typical fashion, one beside the other.
However there is a private method, setNumberOfRows:(int)n that will allow you to set a maximum number of rows to display the buttons in. To use this method we need to add our own additions to the UIAlertView class. We do this by adding an @interface for UIAlertView in our .m file.
// by calling setNumberOfRows.
@interface UIAlertView (extended)
- (void) setNumberOfRows:(int)num;
@end
This will allow us to call the method without the compiler throwing us a warning.
This method call will result in the UIAlertView displaying the buttons on separate rows, the following image depicts the result.
Just like any UIView subclass this object will also respond to you adding subviews, this will allow you to implement UIProgressView’s and other objects such as switches
UIActionSheet, you know, the one that slides up…
UIActionSheet objects are also used throughout the iPhone OS. Apple applications use these to present the user with contextual options, much like a contextual menu on a desktop platform. An example within of a UIActionSheet within an Apple application would be Mail.app When you select the actions button when reading an email you are presented with a UIActionSheet.
Similar to the UIAlertView the action sheet view is allocated and then initialised with parameters such as a title string and an array of buttons. Remember that the list of other button titles must always end with a nil parameter.
delegate:self
cancelButtonTitle:@"Dismiss"
destructiveButtonTitle:@"Delete SMS"
otherButtonTitles:@"Forward SMS", @"Copy SMS", nil];
Again this method will allocate and initialise a UIActionSheet object. Displaying the action sheet requires the showIinView method and it requires a single parameter, the UIView (or subclass) you wish to display the action sheet in. Most of the time, and in this example I will be using the applications key window ([[UIApplication sharedApplication] keyWindow]).
[sheet release];
As soon as you have displayed the view you can release it.
UIProgressHUD, the one they hid from you!
The UIProgressHUD is an alert that isn’t discussed within the API documentation, to use UIProgressHUD we need to create an @interface for it. This ones long. The comment in the code below explains why.
// THIS IS A COPY FROM UIProgressHUD.h from UIKit’s private
// frameworks and should be used with the under standing
// that Apple may wish to deny your app to the App Store
@interface UIProgressHUD : UIView
{
UIProgressView *_progressIndicator;
UILabel *_progressMessage;
UIImageView *_doneView;
UIWindow *_parentWindow;
struct {
unsigned int isShowing:1;
unsigned int isShowingText:1;
unsigned int fixedFrame:1;
unsigned int reserved:30;
} _progressHUDFlags;
}
- (id)_progressIndicator;
- (id) initWithWindow:(UIWindow *)window;
- (id)initWithFrame:(struct CGRect)fp8;
- (void)setText:(id)fp8;
- (void)setShowsText:(BOOL)fp8;
- (void)setFontSize:(int)fp8;
- (void)drawRect:(struct CGRect)fp8;
- (void)layoutSubviews;
- (void)showInView:(id)fp8;
- (void)hide;
- (void)done;
- (void)dealloc;
- (void) show:(BOOL)aShow;
@end
Being a private API UIKit will parse any calls we make or objects we initialise however the compiler will not build our application without an @interface for the UIProgressHUD object so here I simply copied the UIProgressHUD.h from the UIKit Private Headers.
Creating a UIProgressHUD is now as simple as creating and other UI object and control.
UIProgressHUD *HUD = [[UIProgressHUD alloc] initWithWindow:[[UIApplication sharedApplication] keyWindow]];
This object is now allocated, initialised and ready to display. We can set some text for the view, and then display it with the following.
[HUD show:YES];
This will display the alert onscreen see the output below.
This alert can then be told the intermediate action had completed and display a tick in place of a progress indicator, the methods to do this and then remove the alert from superView are show in the interface declaration but for the sake of this tutorial I shall post some code below using timed method calls to change the alert’s state. This code comes directly from the example project so do check it out!
// in different methods.
[HUD performSelector:@selector(done) withObject:nil afterDelay:1.2];
[HUD performSelector:@selector(setText:) withObject:@"Done Somthing!" afterDelay:1.2];
[HUD performSelector:@selector(hide) withObject:nil afterDelay:2.0];
//release the object, save on memory!
[HUD release];
This concludes my article on types of alerts found within iPhones UIKit framework. For information on delegate methods for handling button clicks within the UIAlertView and UIActionSheet please refer to the sample project where its all quite clear and commented. For further information search the class names in the Cocoa Touch documentation either online at developer.apple.com or from within xcode.
The source code contains a copy of the tutorial for use offline as well as the xcode project for you to read through











9 Responses
Cool guide! setNumberOfRows: is exactly what I needed just now. Thanks!
Thanks for this little tidbit.
[sheet showInView:[[UIApplication sharedApplication] keyWindow]];
I was previously attaching the UIActionSheet to my current view controller’s view, but the cancel button was not always responsive to touches. Presenting the sheet from as far up the view hierarchy makes it work flawlessly as intended.
Also thanks for the heads up on the private API. I don’t think I’ll use them any time, but it’s nice to be aware of them… makes filing enhancement requests easier!
@Michael Ayers: Attaching the subview to the keyWindow should normally mean that subview is drawing on top of all other views.
@Seventoes: It’s a pity apple don’t document that call, I know if you have 3+ buttons it draws them in rows, but two buttons side by side looks awful and titles will truncate.
Thanks alot for the information. Really helpful, I wish there were fully explained the documentation :p would love to see more.. Maybe on tableViews or models are topic I am interested in.
Now I know how to get private APIs to work. Thanks!
@Sean G If you want to look into private API’s just google Erica Sadun and class dump, you’ll get a method for dumping all the class definitions for all of the iPhone OS, all the private classes such as message bubbles the progress hud and the hud progress bars
Wow~ Great tutorial! Thanks a lot Tim, I will defiantly be using this
Hey, thanks for getting our app rejected from the appStore for using TOTALLY illegal HUD code.
Why not write *CORRECT* fully legal code instead?
@Connie I clearly stated in the first paragraph of the post that using this API was not permitted by Apple and will therefore not be allowed in the App Store. Please try and remember to read the whole post before trying to blame me for something that is your fault.