Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

iOS Foundations - Stage 9 (API-access)

I'm following along this tutorial, but I can't seem to get it to work. When I run my app, whatever data in the first cell is also displayed in the next 9. I have even downloaded the project and copied some of it, just to rule out silly mistakes. The only main difference is that I do NOT use storyboards. Here is what my AppDelegate.m looks like:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    MainViewController *mainVC = [[MainViewController alloc] initWithStyle:UITableViewStylePlain];
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window setRootViewController:mainVC];
    [self.window makeKeyAndVisible];
    return YES;
}

I don't see the point in showing any more code, as I have followed the lesson from start to finish, with the exceptions of storyboard.

Any help is greatly appreciated.

Sounds like an issue with your table view controller. Can you post your code for that?

#import "MainViewController.h"

@interface MainViewController ()

@end

@implementation MainViewController

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSString *apiKey = @"X2LQdVnTk3gQ8Vh6";    
    NSString *stringURL = [NSString stringWithFormat:
                           @"http://api.eventful.com/rest/events/search?app_key=%@&location=Bergen&country=Norway&category=music&date=future",apiKey];

    self.xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:[NSURL URLWithString:stringURL]];

    self.xmlParser.delegate = self;

    self.eventsArray = [NSMutableArray array];
    self.currentString = [NSMutableString string];

    self.dateFormatter = [[NSDateFormatter alloc] init];
    self.dateFormatter.locale = [NSLocale currentLocale];
    self.dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";

    if ( [self.xmlParser parse] )
        NSLog(@"XML Parsed");
    else
        NSLog(@"Failed to parse");
}

#pragma mark - Table view data source

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Info";

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

    Event *event = [self.eventsArray objectAtIndex:indexPath.row];

    cell.textLabel.text = event.title;
    cell.detailTextLabel.text = event.venueName;

    return cell;
}

#pragma mark -
#pragma mark Parser Delegate

static NSString *kName_Event = @"event";
static NSString *kName_Title = @"title";
static NSString *kName_StartTime = @"start_time";
static NSString *kName_VenueName = @"venue_name";


- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    if ( [elementName isEqualToString:@"event"] ){
        self.currentEvent = [[Event alloc] init];
        self.storeCharacters = NO;
    } else  if ([elementName isEqualToString:kName_Title] || [elementName isEqualToString:kName_StartTime] || [elementName isEqualToString:kName_VenueName]) {
        [self.currentString setString:@""];
        self.storeCharacters = YES;
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    if (self.storeCharacters) [self.currentString appendString:string];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {

    if ([elementName isEqualToString:kName_Title]) {
        self.currentEvent.title = _currentString;
    } else if ([elementName isEqualToString:kName_VenueName]) {
        self.currentEvent.venueName = _currentString;
    } else if ([elementName isEqualToString:kName_StartTime]) {
        self.currentEvent.startTime = [self.dateFormatter dateFromString: _currentString];
    } else if ([elementName isEqualToString:kName_Event]) {
        [self finishedCurrentEvent:_currentEvent];
    }

    self.storeCharacters = NO;

}

- (void) finishedCurrentEvent:(Event*)e{
    [self.eventsArray addObject:e];
    self.currentEvent = nil;
}

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
    // Handle errors as appropriate for your application.
}

- (void)parserDidEndDocument:(NSXMLParser *)parser {
    NSLog(@"%lu",(unsigned long)self.eventsArray.count);
    [self.tableView reloadData];
}
@end

and the .H-file

#import <UIKit/UIKit.h>
#import "Event.h"

@interface MainViewController : UITableViewController <NSXMLParserDelegate>

@property (strong, nonatomic) NSXMLParser *xmlParser;
@property (strong, nonatomic) Event *currentEvent;
@property (strong, nonatomic) NSMutableString *currentString;
@property (strong, nonatomic) NSDateFormatter *dateFormatter;
@property (strong, nonatomic) NSMutableArray *eventsArray;
@property (assign, nonatomic) BOOL storeCharacters;

- (void)finishedCurrentEvent:(Event *)e;

@end

2 Answers

After you call your parseXml method NSLog your events array and see what it contains. Does it contain the same event in each index? If so it's likely a problem with your parse method

I will try that, but those methods are basically copied, and when I download the project it works properly.

it also looks like you are missing the numberOfSectionsInTableView delegate method which could cause some issues ( i assume you just want 1 section?).

Edit: nevermind the default is 1 so you are fine.

I sloved it. In my model, the variables were (strong, nonatomic). Changed it to (copy, nonatomic) and it worked. Need to check out the difference I guess :) Thanks anyway!