Using NSXMLParser to Pull UIImages From the Web

    June 19th, 2009 Posted by: - posted under:Tutorials

    Introduction

    Hello everyone, welcome to my third screeencast. This screencast is the result of a request made in the comments of my first post. I am going to be covering many topics in this post. But the general idea of the app we will build is that it will use an XML file online to get the URL and title of a given picture. For each URL and Title pair a view will be created with a UIImageView showing the image and a UILabel showing the title. Each of these views will be placed in a UIScrollView to flip through, like th functinoality of the Photos app.

    Skill Level Medium

    This app is going to require a decent amount of experience with Objective C and xCode. Also some minimal understanding of XML and XML schema/structure would be valuable.

    Source Code

    Available Here

    Screencast

    I film myself coding out the entire sample project for each post. I personally think going through the Screencast is the best way to learn. But feel free to look through the slides and text if that suites you better.

    from on .

    SCREENCAST ADDITION

    Adding a final line to layoutSubviews should be:
         [scrollview setFrame:workingFrame];
    
    this will stop the scroll view from bouncing up and down.

    Tutorial

    picture-32

    picture-41

    picture-5

    picture-61

    picture-71

    picture-81

    picture-91

    picture-101

    picture-111

    picture-121

    picture-131

    picture-141

    picture-151

    iCodeBlogXMLImagesViewController.h:

    @interface iCodeBlogXMLImagesViewController : UIViewController
    {
            IBOutlet UIScrollView *scrollview;
    }
    
    @property (nonatomic, retain) IBOutlet UIScrollView *scrollview;

    iCodeBlogXMLImagesViewController.m

    @synthesize scrollview;

    picture-161

    picture-171

    picture-181

    picture-191

    iCodeBlogXMLView.h:

    @interface iCodeBlogXMLView : UIView
    {
            IBOutlet UIImageView *imageView;
            IBOutlet UILabel *title;
    }
    
    @property (nonatomic, retain) IBOutlet UIImageView *imageView;
    @property (nonatomic, retain) IBOutlet UILabel *title;
    
    @end

    iCodeBlogXMLView.m

    @synthesize imageView;
    @synthesize title;

    picture-201

    picture-211

    picture-221

    picture-23

    iCodeBlogXMLElement.h:

    @interface iCodeBlogXMLElement : NSObject
    {
            UIImage *image;
            NSString *imageTitle;
    }
    
    @property (nonatomic, retain) UIImage *image;
    @property (nonatomic, retain) NSString *imageTitle;
    
    @end

    iCodeBlogXMLElement.m

    @synthesize image;
    @synthesize imageTitle;

    picture-241

    picture-251

    picture-261

    picture-27

    iCodeBlogXMLImagesViewController.h:

    #import <UIKit/UIKit.h>
    #import "iCodeBlogXMLElement.h"
    #import "iCodeBlogXMLView.h"
    
    @interface iCodeBlogXMLImagesViewController : UIViewController
    {
            IBOutlet UIScrollView *scrollview;
    
            NSXMLParser *parser;
            NSMutableString *currentAttribute;
            NSMutableArray *xmlElementObjects;
    
            iCodeBlogXMLElement *tempElement;
    }
    
    @property (nonatomic, retain) IBOutlet UIScrollView *scrollview;
    
    @property (nonatomic, retain) NSXMLParser *parser;
    @property (nonatomic, retain) NSMutableString *currentAttribute;
    @property (nonatomic, retain) NSMutableArray *xmlElementObjects;
    
    @property (nonatomic, retain) iCodeBlogXMLElement *tempElement;
    
    -(void)layoutSubview;
    
    @end

    iCodeBlogXMLImagesViewController.m

    @implementation iCodeBlogXMLImagesViewController
    
    @synthesize scrollview;
    @synthesize parser;
    @synthesize currentAttribute;
    @synthesize xmlElementObjects;
    @synthesize tempElement;
    
    ...
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
            xmlElementObjects = [[NSMutableArray alloc] init];
    
            parser = [[NSXMLParser alloc] initWithContentsOfURL:[NSURL URLWithString:@"http://losectrl-gaincommand.com/iCodeBlogHelper/Tutorial3/iCodeBlogImageXML.xml"]];
            [parser setDelegate:self];
            [parser parse];
    }
    
    ...
    
    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
    {
    
    }
    
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
    {
    
    }
    
    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
    {
    
    }

    picture-281

    picture-291

    picture-301

    picture-311

    iCodeBlogXMLImagesViewController.m

    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
    {
            if(![elementName compare:@"PictureInfo"])
            {
                    tempElement = [[iCodeBlogXMLElement alloc] init];
            }
    
            else if(![elementName compare:@"imageURL"])
            {
                    currentAttribute = [NSMutableString string];
            }
    
            else if(![elementName compare:@"imageTitle"])
            {
                    currentAttribute = [NSMutableString string];
            }
    }
    
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
    {
            if(![elementName compare:@"PictureInfo"])
            {
                    [xmlElementObjects addObject:tempElement];
            }
    
            else if(![elementName compare:@"imageURL"])
            {
                    NSURL *imageURL = [NSURL URLWithString:currentAttribute];
                    NSData *data =  [NSData dataWithContentsOfURL:imageURL];
                    UIImage *image = [[UIImage alloc] initWithData:data];
    
                    [tempElement setImage:image];
            }
    
            else if(![elementName compare:@"imageTitle"])
            {
                    NSLog(@"The image title is %@", currentAttribute);
                    [tempElement setImageTitle:currentAttribute];
            }
    
            else if(![elementName compare:@"Pictures"])
            {
                    [self layoutSubview];
            }
    }
    
    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
    {
            if(self.currentAttribute)
            {
                    [self.currentAttribute appendString:string];
            }
    }

    picture-321

    iCodeBlogXMLImagesViewController.m

    -(void)layoutSubview
    {
            CGRect workingFrame;
    
            workingFrame.origin.x = 0;
            workingFrame.origin.y = 0;
            workingFrame.size.height = 480;
            workingFrame.size.width = 320;
    
            iCodeBlogXMLView *myView;
    
            for(iCodeBlogXMLElement *element in [self xmlElementObjects])
            {
                    myView = [[iCodeBlogXMLView alloc] initWithFrame:workingFrame];
    
                    NSLog(@"Element title is: %@", [element imageTitle]);
    
                    NSArray *topLeveObjects = [[NSBundle mainBundle] loadNibNamed:@"iCodeBlogXMLView" owner:nil options:nil];
    
                    for(id currentObject in topLeveObjects)
                    {
                            if([currentObject isKindOfClass:[iCodeBlogXMLView class]])
                            {
                                    myView = (iCodeBlogXMLView *)currentObject;
                            }
                    }
    
                    [[myView imageView] setImage:[element image]];
                    [[myView title] setText:[element imageTitle]];
                    [myView setFrame:workingFrame];
    
                    [scrollview addSubview:myView];
    
                    workingFrame.origin.x = workingFrame.origin.x + 320;
            }
    
            workingFrame.size.width = workingFrame.origin.x;
            [scrollview setContentSize:workingFrame.size];
    
            workingFrame.origin.x = 0;
            workingFrame.origin.y = 0;
            workingFrame.size.width = 320;
            workingFrame.size.height = 480;
    }
    
    picture-33
    

    iCodeBlogXMLImagesViewController.m

       parser = [[NSXMLParser alloc] initWithContentsOfURL:[NSURL URLWithString:@"http://losectrl-gaincommand.com/iCodeBlogHelper/Tutorial3/iCodeBlogImageXMLB.xml"]];