可变列表一个特定类的实例

时间:2014-06-27 17:00:09

标签: objective-c cocoa

我希望在Objective-C中跟踪游戏中可变数量的对象,这些对象都是同一个类或继承类的实例。

在Java中我会做类似

的事情
List<MyClass> list = new ArrayList<>();

就是这样。我找不到使用Cocoa / Foundation的同样明显的解决方案。我可以用某种方式使用NSMutableArray吗? 注意,我需要对象具有我想要的特定类型,而不是 id 。我也不想使用类别或从NSMutableArray继承,而只是使用NSMutableArray,以便它返回的内容被转换为我需要的类。

2 个答案:

答案 0 :(得分:1)

Objective-C没有泛型,因此NSArray和NSMutableArray不会以您希望的方式强类型化。尽管如此,解决这个问题非常简单。给定以下代码,您有一个名为list的NSMutableArray,其中的项目为MyClass

NSMutableArray *list = [NSMutableArray new];
MyClass *objectToInsert = [MyClass new];
[list addObject:objectToInsert];

要从数组中检索对象并将其视为指向MyClass类型的指针,只需声明您的变量:

MyClass *myObject = list[0];
myObject.someProperty = someValue;
[myObject doSomething];

Xcode将提供完整的代码完成等。请注意,您不需要使用C风格的演员表;在声明变量时,可以隐式地将任何类型id的变量强制转换为对象指针。您也可以在循环中执行此操作:

for (MyClass *item in list) {
    item.someProperty = someValue;
    [item doSomething];
}

请注意,在您只想传递对象或可能调用一个方法的简单情况下,如果您对此感到满意,可以保留id类型的对象。

[list[0] doSomething];

上面仍然会将消息doSomething发送到MyClass类型的对象,并在该对象上调用正确的方法,假设数组中的对象的类型正确。在执行此操作与前面显示的更明确的语法之间,基本上没有区别。

请注意,编译器或运行时不会检查数组中的项实际上是否为MyClass类型。因此,如果将其他类型的对象插入到数组中,则可能会出现意外行为或运行时错误。根据我的经验,对于大多数代码而言,这通常没有太大的风险。

此外,如评论中所述,您可以使用“强类型”便捷方法创建自定义类来填充和访问NSMutableArray。使用- (void)addWidget:(MyWidget *)obj- (void)insertWidget:(MyWidget *)obj atIndex:(NSInteger)index等签名的方法将允许Xcode在编译时检查插入到数组中的对象的类型,但在某些情况下(如果您有id类型的变量,你仍然可以使用这些方法,没有任何编译时警告或错误,因此允许插入其他类型的对象)。如果你想对它更加防御,可以在这些方法中添加一个断言来在运行时检查类型:

- (void)addWidget:(MyWidget *)obj
{
    NSAssert([obj isKindOfClass:[MyWidget class]]);
    [self.list addObject:obj];
}

根据我的经验,虽然我发现这一切都比它的价值更大,除非你有一些重要的逻辑与数组的操作相关联。


请注意,Swift确实有一个完整的泛型实现。

答案 1 :(得分:0)

它违背了客观的概念。在objective-c中,您可以将任何选择器发送到任何对象。

然而,workaround就是{{3}}。我没有使用这个库,所以我不能说它是否方便,但它可能是你想看的东西。