【问题标题】:Mutable List of instances of one specific class [duplicate]一个特定类的实例的可变列表[重复]
【发布时间】:2014-06-27 17:00:08
【问题描述】:

我想在游戏中跟踪可变数量的对象,它们都是 Objective-C 中同一类或继承类的所有实例。

在 Java 中我会做类似的事情

List<MyClass> list = new ArrayList<>();

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

【问题讨论】:

  • 纠正你自己的集合类或 NSMutableArray 上的一个类别来检查你插入的类型并不难,但就基础类而言,这样的东西不存在。
  • 在 Obj-C 中没有类似的东西。即使在 Java 泛型 1.5 中,它们从一开始就没有。
  • 从好的方面来说它确实存在于 swift 中!
  • 关于“重复答案”:我之前看过链接的问题,但对答案不太满意。我的问题的公认答案正是我正在寻找的(一种使用 NSMutableArray 的方法,但仍然能够取出对象并使它们成为我想要的类型,而不是 id)。我是否应该尝试改写我的问题以指出使用 NSMutableArray 而不必修改或继承它的重点?

标签: objective-c cocoa


【解决方案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 类型。因此,如果将其他类型的对象插入到数组中,可能会出现意外行为或运行时错误。以我的经验,这对于大多数代码来说通常没有太大的风险。

此外,如 cmets 中所述,您可以创建一个自定义类,使用“强类型”便捷方法来填充和访问 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 确实有一个完整的泛型实现。

【讨论】:

  • 谢谢,这和我预期的一样。我试图显式转换它,但效果不佳,所以我没想到隐式转换会起作用。哦,是的,期待 Swift,但我也希望能够正确使用 Obj-C :)
【解决方案2】:

这违反了objective-c 概念。在 Objective-c 中,你可以将任何选择器发送到任何对象。

但是有一个workaround 。我没有使用这个库,所以我不能说它是否方便,但你可能想看看它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-26
    • 2015-04-02
    • 1970-01-01
    相关资源
    最近更新 更多