Question

I have created an application that is almost a clone of Apple's SeismicXML sample application so that I can learn the ins and outs of the NSXMLParser. I created my very own .xml file and copied most if not all of the code from the SeismicXML app to my app called XMLTest. Everything seems to run great except for one part. When the app is running, all of the text fields show the same data. No matter which property of the parse I set the textField.text to show, it all shows the same data, which happens to be the last element parsed.

During debugging, I went into the parsing operation and implemented many NSLog statements to see what data was being parsed. All of the NSLog statements show the correct elements of the .xml file are being parsed and set to the correct properties of the correct object.

I'm not sure what part of my code is wrong and I've been debugging this app by myself for too many hours. I've enclosed parts of the code I feel may be the culprit of the issue.

In this code snippet, the value of both labels is the same, which it shouldn't be.

@implementation VTSVehicleTableViewCell

-(void)configureWithVehicle:(VTSVehicle *)vehicle {

self.stockLabel.text = vehicle.stock;
self.infoLabel.text = vehicle.year;

}

Here is what this generates in the simulator:

Simulator Picture

However, right inside of this method, it is generating the following correct information in the console:

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {

if (_accumulatingParsedCharacterData) {
    // If the current element is one whose content we care about, append 'string'
    // to the property that holds the content of the current element.
    //
    NSLog(@"%@", string);
    [self.currentParsedCharacterData appendString:string];
    NSLog(@"%@", string);
}
}

Console Information

Its like the vehicle object has the right data in it during and after the parsing of the xml, but when i go to update the view, the data in the vehicle object is now only populated with the data that is inside the last element of the xml file. Here is what the xml file looks like:

<vehicles published="2014-04-02">
<vehicle>
    <stock>003737</stock>
    <serial>WVWDM7AJ2BW166848</serial>
    <year>2011</year>
    <make>VOLKSWAGEN</make>
    <model>GOLF</model>
    <date>01/05/11</date>
    <price>26540.00</price>
    <invoice>25414.00</invoice>
    <trim>4DR TDI 6SP AUT</trim>
</vehicle>
<vehicle>
    <stock>003974</stock>
    <serial>3VWLL7AJ1CM317028</serial>
    <year>2012</year>
    <make>VOLKSWAGEN</make>
    <model>JETTA</model>
    <date>11/03/11</date>
    <price>0.00</price>
    <invoice></invoice>
    <trim>2.0L TDI 6SP AUTO</trim>
</vehicle>
<vehicle>
    <stock>004104</stock>
    <serial>1VWBH7A38CC061891</serial>
    <year>2012</year>
    <make>VOLKSWAGEN</make>
    <model>PASSAT</model>
    <date>03/05/12</date>
    <price>26665.00</price>
    <invoice>25555.00</invoice>
    <trim>SE W/SR 2.5 6SP AUTO</trim>
</vehicle>
</vehicles>

Why do the text labels show the same data, even though they are pulling from different properties on the same object?

EDIT: Here is the code for cellForRowAtIndexPath:

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

static NSString *kVehicleCellID = @"VehicleCellID";
VTSVehicleTableViewCell *cell = (VTSVehicleTableViewCell *)[tableView dequeueReusableCellWithIdentifier:kVehicleCellID];

// Get the specific vehicle for this row.
VTSVehicle *vehicle = (self.vehicleList)[indexPath.row];

[cell configureWithVehicle:vehicle];

return cell;
}

Here is the code for the tableViewCell:

#import "VTSVehicleTableViewCell.h"
#import "VTSVehicle.h"

@interface VTSVehicleTableViewCell ()

// References to the subviews which display the earthquake data.
@property (nonatomic, weak) IBOutlet UILabel *stockLabel;
@property (nonatomic, weak) IBOutlet UILabel *infoLabel;

@end

@implementation VTSVehicleTableViewCell

-(void)configureWithVehicle:(VTSVehicle *)vehicle {

    self.stockLabel.text = vehicle.stock;
    self.infoLabel.text = vehicle.year;

}

@end
Was it helpful?

Solution

The problem is not in foundCharacters, but more likely in didStartElement or didEndElement. What's probably happening is that you have a NSMutableString instance that you're using again and again for every element, and then using that element value in your model.

When you save the results of currentParsedCharacterData in didEndElement, you should make sure that you're copying the value (not just using a reference to the existing NSMutableString. For example, you might use a NSString property defined as a copy property, not a strong property. Alternatively, if you're just throwing it in a dictionary or array, use [self.currentParsedCharacterData copy] rather than just currentParsedCharacterData. That will make sure that every element you save in your model ends up as a separate NSString instance (and, by the way, ensures that those objects are no longer mutable).

Clearly, as matt suggested, there could be a simple problem in your cellForRowAtIndexPath, but I suspect that the NSXMLParserDelegate code is the more likely culprit.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top