Making an array of Objects in Objective-C.

85,165

Solution 1

Here is an example that creates an NSMutableArray instance variable in the Controller class and adds a Person object to that array each time you evoke doSomeWork:

@interface Controller

NSMutableArray *personArray;

@end
@implementation Controller

- (void) viewDidLoad {
    ................
    NSMutableArray *personsArray = [[NSMutableArray alloc] initWithCapacity:40];
}

- (IBAction)doSomeWork {
    Person *myPerson = [[Person alloc] init];
    myPerson.name = name;
    myPerson.age = age;

    [personsArray addObject:myPerson];
}
@end

Solution 2

Arrays in Objective-C with Cocoa/CocoaTouch are quite different from Java. The three main differences are:

  1. The Obj-C arrays are just classes like any other, and have no built-in support in the language. In Java, arrays have a built-in support in the language through the [] operators.

  2. The Obj-C arrays are untyped, they take any object that inherits from NSObject. This means that you can mix types within the same array, although this is probably bad practice unless you have a very good reason to. (Note that int, double, char, BOOL and other built-in types do not inherit from NSObject, so you'd have to wrap them in NSNumber objects if you ever wanted to hold them in an array.)

  3. The Obj-C arrays don't really have a concept of a fixed length, unless the whole array is immutable. So you don't need to decide on length when you create the array.

To create a mutable array, i.e. one where you're allowed to change the objects (and even add and remove objects, changing the array's length), you create an NSMutableArray:

myArray = [[NSMutableArray alloc] init];
// Could also use initWithCapacity: 40, but not necessary.

To add an object, such as an instance of your Person, you call the addObject: method, either making a new Person right there, or giving it a pointer to an existing one:

[myArray addObject: [[[Person alloc] init] autorelease]];
[myArray addObject: someOtherPerson];
// Last line adds some other person I already had a pointer to.

To remove an object, you can use removeObjectAtIndex: or removeLastObject. To replace, you call replaceObjectAtIndex:withObject:. To insert an object in the middle of your array (and remember, this will also increase the size of the array), you call insertObject:atIndex:.

That covers the most important mutating methods, i.e. those specific to NSMutableArray. Of course, you also have the methods that only observes an array, and those are defined in NSArray. The most important ones are count, giving the current number of elements, and objectAtIndex:, giving the object at the index you provide.

Supposing you have some Person objects in your array, you can iterate over them like this:

for (int i = 0; i < [myArray count]; i++) {
    Person* p = [myArray objectAtIndex: i];
    // Do something with p 
}

You might wonder how you'd create an NSArray as such, if you're not allowed to add to it. Well, one of its constructors is initWithObjects:, which allows you to write a comma-separated list of objects to add (and you need to end with a nil value). Another is initWithArray:, which allows you to pass another array (which could be mutable), and the constructor will use the objects from the provided array when making the new one.

Share:
85,165
Admin
Author by

Admin

Updated on July 09, 2022

Comments

  • Admin
    Admin almost 2 years

    Been playing around with XCode for about 2 weeks now, and reading about MVC a bit. I have a problem trying to connect the Model to the Controller because I find it hard to get my head around arrays. I can handle simple arrays when i programmed some in Java but I'm quiet intimidated by the Obj-C NSArrays I see.

    If somebody would be so kind to show me some simple calls on an array of objects i would be eternally grateful.

    My model:

    Person.h

    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject 
    {
    NSString *name;
    NSNumber *age;
    }
    
    @property(nonatomic, retain) NSString *name;
    @property(nonatomic, retain) NSNumber *age;
    
    @end
    

    Person.m

    #import "Person.h"
    @implementation Person
    @synthesize name;
    @synthesize age;
    @end
    

    I've kept if very simple while I try and learn.

    Now my Controller class. What i want to do is create an array of 40 'Person' objects. But i don't know the correct way to put that in code in Obj C.

    Controller.h

    #import <Foundation/Foundation.h>
    @class Person;
    @interface Controller : NSObject 
    {
    Person *person;
    }
    @property(nonatomic, retain) Person *person;
    
    -(void) doSomeWork;
    
    @end
    

    Controller.m

    #import "Controller.h"
    #import "Person.h"
    
    @implementation Controller
    
    @synthesize person;
    
    
    -(IBAction)doSomeWork
    {
    // I guess here is where i should create my array of 40 person objects
    }
    
    @end
    

    My problem is in how to declare the array of person objects of size 40. And then how to access the array to read and write to it.

    Thanks in advance for reading my post.

  • Admin
    Admin over 13 years
    :) I think i am starting to get it now! So in your last code snipper above you get an instance of person back out of the array and store it in 'p'. So i could then check the data of that object by doing something like int personAge = p.age; or if i wanted to update that object i could change p.age = 24; then write p back into the array in that index using replaceObjectAtIndex:p:index
  • harms
    harms over 13 years
    @Code: Correct, except the last point. If you did p.age = 24, then that would be reflected immediately in the Person object stored in the array. You're on to a central part of programming language semantics here: When you call objectAtIndex:, you get a pointer to an already existing Person, you don't get a copy of Person which you can change and then put back in.
  • Admin
    Admin over 13 years
    Awhh! Thats really cool. And a little crazy that i didnt know that -.-
  • Hot Licks
    Hot Licks about 11 years
    It should be pointed out that, with the later versions of Xcode, the [] notation for indexing NSArrays is supported, in addition to the previously-defined method calls.
  • JohnK
    JohnK almost 11 years
    Great! Now how do I access name and age of each element of the personsArray?
  • D. Wonnink
    D. Wonnink almost 11 years
    @JohnK for(Person *person in personsArray) { NSLog(@"Persons age: %@", person.age); NSLog(@"Persons name: %@", person.name); }
  • John Ballinger
    John Ballinger over 10 years
    ?Autorelease on this line? Otherwise you are chewing up memory. Person *myPerson = [[[Person alloc] init] autorelease];
  • Eric Leschinski
    Eric Leschinski over 10 years
    lincb, you added a syntax error to harms post. The change you made caused the left most square braces to have an unmatched right square brace. User needs to have edit privileges reduced.