在Objective-C中创建一个对象数组。

21

我已经开始尝试使用 XCode 大约两周时间了,也读了一些关于 MVC 的文章。我在尝试将 Model 连接到 Controller 时遇到了问题,因为我觉得很难理解数组。我可以处理一些简单的 Java 数组,但是我对我看到的 Obj-C 中的 NSArrays 感到有些害怕。

如果有人能够友好地向我展示一些关于对象数组的简单调用,我将非常感激。

我的 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

在我试着学习的时候,我把它简单化了。

现在是我的 Controller 类。我想要做的是创建一个由 40 个 'Person' 对象组成的数组。但我不知道在 Obj C 中正确地用代码实现这一点。

Controller.h

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

-(void) doSomeWork;

@end

控制器.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

我的问题在于如何声明一个大小为40的person对象数组,以及如何访问该数组以读写其中的内容。

提前感谢您阅读我的帖子。


1
不要感到害怕。Objective-C数组就像Java的ArrayList<Object>一样。它可以像ArrayList一样增长和缩小,并且可以容纳任何对象(您可以在数组中混合对象类型)。 - Itai Ferber
它不像一个数组列表。它不能增长/缩小 - 只有可变数组可以。 - Daij-Djan
2个回答

52

在 Cocoa/CocoaTouch 中,Objective-C 的数组与 Java 中的相当不同。它们有三个主要区别:

  1. Obj-C 数组只是像其他类一样的类,并没有语言内置的支持。在 Java 中,通过 [] 运算符,数组是语言内置支持的。

  2. Obj-C 数组是无类型的,可以接受任何继承自 NSObject 的对象。这意味着您可以在同一个数组中混合使用不同类型的对象,但除非您有非常好的理由,否则这可能是不好的做法。(请注意,intdoublecharBOOL 和其他内置类型都不继承自 NSObject,因此如果您想将它们保存在数组中,则需要将它们包装在 NSNumber 对象中。)

  3. Obj-C 数组没有固定长度的概念,除非整个数组是不可变的。所以创建数组时不需要决定其长度。

要创建可变数组,即您被允许更改其中的对象(甚至添加和删除对象,改变数组的长度),您需要创建一个 NSMutableArray

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

要添加一个对象,比如你的Person实例,你需要调用addObject:方法,可以直接创建一个新的Person,也可以给它一个指向已有对象的指针:

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

要移除一个对象,你可以使用removeObjectAtIndex:removeLastObject。要替换一个对象,你需要调用replaceObjectAtIndex:withObject:。要在数组的中间插入一个对象(请记住,这也会增加数组的大小),你需要调用insertObject:atIndex:

这些是最重要的可变方法,即那些特定于NSMutableArray的方法。当然,你还有一些仅观察数组的方法,这些方法在NSArray中被定义。最重要的两个是count,它提供当前元素的数量,以及objectAtIndex:,它提供你所提供的索引处的对象。

假设你的数组中有一些Person对象,你可以像这样迭代它们:

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

如果你不允许向NSArray添加元素,那么你可能想知道如何创建一个类似的数组。其实,NSArray有两个构造函数可以使用:initWithObjects:,它允许你编写一个逗号分隔的对象列表来添加(必须以nil值结尾);另一个是initWithArray:,它允许你传递另一个数组(可以是可变的),构造函数将使用提供的数组中的对象来创建新的数组。


我觉得我现在开始明白了!所以在你上面的最后一个代码片段中,你从数组中获取了一个人的实例并将其存储在“p”中。那么我可以通过像这样做一些事情来检查该对象的数据,例如int personAge = p.age;或者如果我想更新该对象,我可以更改p.age = 24;然后使用replaceObjectAtIndex:p:index将p写回该索引处的数组中。 - user440096
@代码:除了最后一点外,都是正确的。如果您执行了 p.age = 24,则会立即反映在存储在数组中的 Person 对象中。您正在探讨编程语言语义的核心部分:当您调用 objectAtIndex: 时,您会获得一个指向已经存在的 Person指针,而不是您可以更改然后放回的 Person 的副本。 - harms
哇!那真的很酷。而且有点疯狂,我居然不知道那个。-.- - user440096
应该指出的是,随着Xcode的后续版本,支持使用[]符号来索引NSArrays,除了之前定义的方法调用。 - Hot Licks
1
lincb,你在 harms 的帖子中添加了语法错误。 你所做的更改导致最左边的方括号没有匹配的右方括号。 用户需要降低编辑权限。 - Eric Leschinski

29

这是一个示例,它在Controller类中创建了一个NSMutableArray实例变量,并在每次调用doSomeWork时向该数组添加一个Person对象:

@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

1
太好了!现在我该如何访问personsArray中每个元素的nameage呢? - JohnK
2
@JohnK for(Person *person in personsArray) { NSLog(@"人的年龄: %@", person.age); NSLog(@"人的名字: %@", person.name); } - D. Wonnink
在这一行加上自动释放池,否则会占用内存。Person *myPerson = [[[Person alloc] init] autorelease]; - John Ballinger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接