It's no mystery why writing applications for an iOS device, such as the iPad or iPhone, is a very popular activity: The devices are gorgeous and easy to use. With millions of users, the devices are very lucrative for application development. People enjoy viewing their photos on the beautiful display on iPads and iPhones.
In this article, learn to build an iOS photo slideshow application from scratch. You'll put some XML code and photos on the server, build the iOS application, add an image view, get the XML, and do the slideshow animation.
The back end of the example slideshow application is really just an XML file that you can drop on your server. Listing 1 shows the example XML, with some sample images.
Listing 1. photos.xml
<photos> <photo url="http://localhost/photos/CRW_0675.jpg" /> <photo url="http://localhost/photos/CRW_1488.jpg" /> <photo url="http://localhost/photos/CRW_3273.jpg" /> <photo url="http://localhost/photos/CRW_3296.jpg" /> <photo url="http://localhost/photos/CRW_3303.jpg" /> <photo url="http://localhost/photos/CRW_3359.jpg" /> <photo url="http://localhost/photos/CRW_3445.jpg" /> <photo url="http://localhost/photos/CRW_3752.jpg" /> <photo url="http://localhost/photos/CRW_3754.jpg" /> <photo url="http://localhost/photos/CRW_4525.jpg" /> <photo url="http://localhost/photos/CRW_4547.jpg" /> <photo url="http://localhost/photos/CRW_4700.jpg" /> <photo url="http://localhost/photos/CRW_4860.jpg" /> </photos> |
The XML is remarkably simple. The <photos> tag contains multiple <photo> tags. Each <photo> tag has the URL of the image you want to display. The URL needs to be fully qualified and absolute; the client application will load the URL directly—not through any type of browser that handles relative URLs.
To complete the back end, modify the XML to include references to your photos and upload that XML to a known location on your server. If everything goes as planned, you should be able to browse to the XML using Safari (or whatever browser you choose) and see something like Figure 1.
Figure 1. XML on the server
Figure 1 shows the XML from Listing 1 formatted as text. The result will be different from browser to browser, as this is just simple XML (and there is no standard among browsers).
To test that the URLs are correct:
- Select one of the URLs.
- Copy and paste it into the browser URL area.
- Press the Return key.
You should see something similar to Figure 2.
Figure 2. One of the photos on the server
A photo, located on the server, is referenced by one of the URLs in the XML. If you don't see the XML, or don't see the photos, then you need to check your web server configuration and your URLs. If you can't see a photo in the browser, then your new iOS application can't see it either.
Building the client slideshow application
After the server is configured and the photos are uploaded, you can start to build the iOS application. The first step is to install the Apple Developer Tools (see Resources for a link). If you are:
- Pre-Lion, you need to download the developer tools from the Apple Developer Site (see Resources for a link).
- Running Lion, you can use the Mac App Store to download the tools (see Resources for a link).
After you install the developer tools, run the XCode environment, which is Apple's IDE for both iOS and Mac OS X development. From the XCode environment, select the menu option for a New Project. You should see the first page of the application wizard that you'll use to build iOS or Mac OS X applications, as in Figure 3.
Figure 3. Application wizard
You can choose from several different application templates. For this example, select View-based Application and click Next. You should see the final page of the wizard, as in Figure 4.
Figure 4. Project options
On the second page of the wizard, name your application and select the default
device family (iPad or iPhone). The Product Name of the example application is slideshow. The value in the Company Identifier field indicates the
application is in the com.jherrington
namespace. (Of course, you can choose whatever name and company identifier you like.)
Choose iPad for the Device Family and click Next.
The project is created. At this point it's always best to select the big Play button at the upper left of the interface to run your application for the first time. This step compiles everything and brings up the iPad emulator.
The next step is to add the image view for displaying the images. The iOS framework comes with a rich set of built-in controls that you can use to build your application. For the example, you'll use the UIImageView control. With UIImageView you can display images that are compiled into the application, stored locally on the device, or, as in the example, downloaded from a website.
To add the UIImageView, open the slideshowControllerView.XIB file, which is the user interface definition file for the slideshowControllerView. With the XIB open, go to the object palette and select Image View, as in Figure 5.
Figure 5. Add a UIImageView object to the view controller XIB
With the Image View selected, drag and drop it onto the slideshowControllerView. Usually the IDE auto-scales the control to fit the available space. If it doesn't, simply drag the control to adjust its size until it fills the entire display area.
After the control is on the view, set some of the parameters to get the optimal look and feel for the application. Figure 6 shows the settings on the attributes screen for the Image View control.
Figure 6. Configure the UIImageView
The two modifications you need to make are to the Mode and the Background. Set the Mode to Aspect Fit so the image is scaled but still preserves the aspect ratio of the original. If you don't use Aspect Fit, your images will stretch and scale to match the display area of the image view—and that can end up looking fairly funky.
Because the image might not always fit the available area, you also need to set the Background attribute to Dark Text Color or use the color picker to select a deep black. By default, this value is white. Most photos don't look good when bracketed in a brilliant white.
Save the XIB file and move over to the SlideshowViewController.h file. Make the small modification in Listing 2.
Listing 2. SlideshowViewController.h
#import <UIKit/UIKit.h>
@interface slideshowViewController : UIViewController {
IBOutlet UIImageView *imgView;
}
@end |
You need to add an Outlet to the slideshowViewController
that allows the control defined in the XIB to connect to the view controller class.
After the outlet is added, return to the XIB file, select the UIImageView,
and use the connections inspector to hook the UIImageView object to the imgView variable in the slideshowViewController class.
After that connection is made, then make the code modifications to the slideshow view controller class itself to load an image. Listing 3 shows the complete first version of the class.
Listing 3. SlideshowViewController.m
#import "slideshowViewController.h"
@implementation slideshowViewController
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *imageURL = [NSURL URLWithString:@"http://localhost/photos/CRW_0675.jpg"];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
[imgView setImage:image];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
@end |
The serious work in the slideshowViewController class is done in the viewDidLoad method, which now:
- Loads the data from a URL.
- Turns that into an image.
- Uses the
setImagemethod on the image view to display the image.
At this point, you should run the application to test whether an image comes up. You should see something similar to Figure 7, which shows an image displayed in the iPad emulator.
Figure 7. First image from the server
If you don't see the image, the problem is likely with the setImage method call to imgView. Verify that the UIImageView object is properly connected to the imgView variable. If
the application fails before that, you might not have the correct URL, or something
isn't correct on the server.
Now that you have a way to display the images on an iPad, the next step is to load the XML to get a list of all of the images to display. The iOS framework has a built-in XML parser, so you simply need to create the parser object and listen for the callbacks for the various tags.
Extend the class itself with the NSXMLParserDelegate
interface, which tells the iOS framework that this class is capable of receiving
callbacks from the XML parser. You also need to add an array called photos that holds the list of URLs that are extracted from the XML.
Listing 4 shows the updates.
Listing 4. SlideshowViewController.h with photos
#import <UIKit/UIKit.h>
@interface slideshowViewController : UIViewController<NSXMLParserDelegate> {
IBOutlet UIImageView *imgView;
NSMutableArray *photos;
}
@end |
As you write more iOS applications, you'll find that you use more and more delegates to connect to various APIs. There are data callbacks for tables, UI elements, GPS callbacks, and more. You can even create your own custom interfaces for your own libraries.
To use the XML parser, extend the view controller class, as in Listing 5.
Listing 5. SlideshowViewController.m with photos
- (void)viewDidLoad
{
[super viewDidLoad];
photos = [[NSMutableArray alloc] init];
NSXMLParser *photoParser = [[[NSXMLParser alloc]
initWithContentsOfURL:
[NSURL URLWithString:@"http://localhost/photos/index.xml"]] autorelease];
[photoParser setDelegate:self];
[photoParser parse];
NSURL *imageURL = [NSURL URLWithString:[photos objectAtIndex:0]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
[imgView setImage:image];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict {
if ( [elementName isEqualToString:@"photo"]) {
[photos addObject:[attributeDict objectForKey:@"url"]];
}
} |
The class now creates a parser in the viewDidLoad method and
has it request and parse the XML from the server. It also sets the delegate for the
parser back to itself so that it gets callbacks.
In the example, you want to listen for
the didStartElement callback that is triggered whenever a
tag is encountered. The didStartElement function then
looks at the tag name to see if it's a photo tag. If it is, didStartElement adds the value of the url attribute to the photos array.
After the array of photos is completed, the viewDidLoad method continues and sets the
image to the first image in the array.
Run the application to test your progress. You should see the first image specified in
the XML appear in the emulator. If you don't see the first image, you might have an
issue with the XML on the server. Set a breakpoint in the didStartElement method to see if it is getting called. If it isn't,
then you aren't getting any valid XML back from your sever.
The final step is to use the array of photos to animate a slideshow. You will need two things:
- A timer
- A variable to hold your current location in the slideshow
Add both of these items to the class definition, as in Listing 6.
Listing 6. SlideshowViewController.h completed
#import <UIKit/UIKit.h>
@interface slideshowViewController : UIViewController<NSXMLParserDelegate> {
IBOutlet UIImageView *imgView;
NSMutableArray *photos;
NSTimer *timer;
int currentImage;
}
@end |
The timer is an object that will fire off events at an
interval that you specify. The
currentImage is simply an index into the photos array that
you will use to iterate through all of the images.
Listing 7 shows the final version of the slideshow application code.
Listing 7. SlideshowViewController.m completed
#import "slideshowViewController.h"
@implementation slideshowViewController
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
photos = [[NSMutableArray alloc] init];
NSXMLParser *photoParser = [[[NSXMLParser alloc]
initWithContentsOfURL:[NSURL URLWithString:
@"http://localhost/photos/index.xml"]] autorelease];
[photoParser setDelegate:self];
[photoParser parse];
currentImage = 0;
NSURL *imageURL = [NSURL URLWithString:[photos objectAtIndex:0]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
[imgView setImage:[UIImage imageWithData:imageData]];
timer = [NSTimer scheduledTimerWithTimeInterval: 5.0
target: self
selector: @selector(handleTimer:)
userInfo: nil
repeats: YES];
}
- (void) handleTimer: (NSTimer *) timer {
currentImage++;
if ( currentImage >= photos.count )
currentImage = 0;
NSURL *imageURL = [NSURL URLWithString:[photos objectAtIndex:currentImage]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
[imgView setImage:[UIImage imageWithData:imageData]];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict {
if ( [elementName isEqualToString:@"photo"]) {
[photos addObject:[attributeDict objectForKey:@"url"]];
}
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
@end |
The two new elements in Listing 7 are the creation of
the timer in the viewDidLoad method and the addition
of the handleTimer method, which is called when the
timer fires. The handleTimer method simply
increments the currentImage, then rolls the index around if it hits the end of the array. It also uses the standard image fetching logic to get the image at the given index and display it.
Timers have two modes: They can fire once, or they can fire continuously.
In the viewDidLoad method, the example specifies YES
for repeats so that the handleTimer method is called over and over for the lifetime of the application.
In this article, you created a basic iOS application. You can now take the application in several different directions. The iOS CoreGraphics framework provides a rich set of transitions that you can use to animate the change between the images. You can use PHP on the back end to generate the XML dynamically. Or, you can even use the CoreAudio API to put some music behind the whole slideshow.
Learn
- Apple Developer Portal: Get the IDE, provision your test devices, and upload finished apps to the store.
- iOS Developer Library: Learn the basics about iOS development by reading the Getting Started documents from this bookshelf of detailed information essential to iOS application development.
- The W3C: Peruse various standards. The XML standard is especially relevant to this article.
- The Objective-C language: Apple has documentation if you need to brush up on Objective-C unique syntax.
- Building an iPhone chat app from the ground up: (Jack D. Herrington, developerWorks, January 2011): Learn the process for building an iPhone chat application from the server all the way to the user interface on the front end.
- More articles by this author (Jack Herrington, developerWorks, March 2005-current): Read articles about Ajax, JSON, PHP, XML, and other technologies.
- New to XML? Get the resources you need to learn XML.
- XML area on developerWorks: Find the resources you need to advance your skills in the XML arena, including DTDs, schemas, and XSLT. See the XML technical library for a wide range of technical articles and tips, tutorials, standards, and IBM Redbooks.
- IBM XML certification: Find out how you can become an IBM-Certified Developer in XML and related technologies.
- developerWorks technical events and webcasts: Stay current with technology in these sessions.
- developerWorks on Twitter: Join today to follow developerWorks tweets.
- developerWorks podcasts: Listen to interesting interviews and discussions for software developers.
- developerWorks on-demand demos: Watch demos ranging from product installation and setup for beginners to advanced functionality for experienced developers.
Get products and technologies
- Mac App Store: Download and install apps on your Mac.
- IBM product evaluation versions: Download or explore the online trials in the IBM SOA Sandbox and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
Discuss
- developerWorks profile: Create your profile today and set up a watchlist.
- XML zone discussion forums: Participate in any of several XML-related discussions.
- The developerWorks community: Connect with other developerWorks users while exploring the developer-driven blogs, forums, groups, and wikis.




