views:

505

answers:

2

An iPhone question for you guys! I have an NSURLConnection that downloads XML from a server and processes it into an array which is a part of another array. I have no way of knowing how many objects I will need, so I cannot allocate an NSArray beforehand. My question is:

Would it be better to create the parent array as an NSArray at the class level and allocate it after I store the data in a temporary NSMutableArray or just make the NSMutableArray at class level? It is worth noting that I do not need to modify the array other than to release it at the end of the program run.

+1  A: 

I don't think it really matters.

I'm reading the Beginning iPhone 3 Development book at the moment, and usually loading the data is done like this: You'd have an NSArray property :

@interface
{
...
    NSArray *listOfObjects;
...
}
@property (nonatomic, retain) NSArray *listObObjects;
...

Then you create an NSMutableArray, load your data and set the property:

NSMutableArray *array = [[NSMutableArray alloc] init]; // ?
// load the XML into array here
...
self.listOfObjects = array;
[array release];

listOfObjects would then be treated as an NSArray (immutable) although it actually would be an NSMutableArray.

Thomas Müller
A: 

I think what you probably want to do is create some Classes that match what you are representing in your xml. For example if you xml looks something like this:

<peopleList>
  <person>
    <name>Joe</name>
    <possession>Shovel</possession>
  </person>
  <person>
    <name>Sam</name>
    <possession>Shovel</possession>
    <possession>Fork</possession>
    <possession>Backpack</possession>
  </person>
</peopleList>

You should have a PeopleList Class and a Person Class. An object instantiated from the PeopleList Class has your first array that contains one or more Person objects. The Person objects, in turn, also have arrays to hold the possesions (which in this case are strings - although if needed they could be Possesion objects) In this case, to help the example the Person Class also has another property: 'name' which is also a String.

For example:

@interface PeopleList {
    NSMutableArray *persons;  // An array to store the Person objects
}
@property (nonatomic, retain) NSMutableArray *persons;    
@end



@interface Person {
    NSString *name;  
    NSMutableArray *possesions; //An array to store this Person's possesion strings
}
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSMutableArray *possesions;
@end

In the init method's of these objects you will have to alloc/init the arrays so they will be ready to receive objects. And because I alloc'd them, my class is responsible for the release.

@implementation PeopleList
    -(id) init {
        if (self = [super init]) {
             persons = [[NSMutableArray alloc] init];
        }
    }

    -(void) dealloc {
       [persons release];
       [super dealloc];
    }
@end


@implementation PeopleList
    -(id) init {
        if (self = [super init]) {
             possesions = [[NSMutableArray alloc] init];
        }
    }

    -(void) dealloc {
       [possesions release];
       [super dealloc];
    }
@end

Now that this is done, you can set up your data structure of cascading array's. As you are parsing the XML when you come across a PeopleList Tag do a:

currentPeopleList = [[PeopleList alloc] init];

and when you come across a Person tage do a:

currentPerson = [[Person alloc] init];
[peopleList.persons addObject: person];

a possesion:

[currentPerson.possesion addObject: contentsOfCurrentElement];

or name:

currentPerson.name = contentsOfCurrentElement;

But to answer your more specific question, I not store the data in a temporary NSArray and then copy that into a NSMutableArray. There is almost no performance gain by doing so, and you will burn cpu cycles and memory doing the copy.

Brad Smith