【问题标题】:How do I extend an NSArray?如何扩展 NSArray?
【发布时间】:2012-02-16 09:13:18
【问题描述】:

这是我的尝试:

H 文件:

@interface Strings : NSArray
@end

M 文件:

@implementation Strings
- (id) init
{
    [self initWithObjects:
     @"One.",
     nil];
    return self;
}
@end

当我跑步时,我得到了这个:

'NSInvalidArgumentException',原因:'* -[NSArray initWithObjects:count:]:仅为抽象类定义的方法。定义 -[Strings initWithObjects:count:]!'

这就是我所做的:

H 文件:

@interface Strings : NSObject
+ (NSArray*) getStrings;
@end

M 文件:

@implementation Strings
+ (NSArray*) getStrings
{
    NSArray* strings = [[NSArray alloc] initWithObjects:
     @"One.",
     nil];
    return strings;
}
@end

【问题讨论】:

  • 我以为我可以扩展 NSArray 但即使它编译它也会崩溃。我最终在我所有模型的基类中编写了一个像你这样的静态函数。由于它是静态函数,我可以使用[[self alloc] init] 创建项目并附加到数组。

标签: objective-c ios nsarray extend


【解决方案1】:

您应该避免从NSArray 派生。来自文档:

请记住,NSArray 是类集群的公共接口,它对您的子类意味着什么。 NSArray 的原始方法不包括任何指定的初始值设定项。这意味着您必须为子类提供存储并实现直接作用于该存储的原始方法。

这意味着当你初始化一个数组时,你不会得到NSArray 的实例。您将获得一个完全不同的类的实例,该类仅具有相同的接口。这就是为什么子类化不像你认为的那样工作的原因:你必须自己完全实现存储。这就是文档进一步指出的原因:

NSArray 的任何子类都必须覆盖原始实例方法 count 和 objectAtIndex:。这些方法必须在您为集合元素提供的后备存储上运行。对于这个后备存储,您可以使用静态数组、标准 NSArray 对象或其他一些数据类型或机制。您还可以选择部分或全部覆盖您想要为其提供替代实现的任何其他 NSArray 方法。

最后但并非最不重要的一点是,无论如何您都会遇到初始化错误。你需要打电话给super

- (id)init
{
    self = [super initWithObjects:@"One", @"Two", nil];
    if (!self) return nil;

    return self;
}

但正如我刚才所说,它并不那么容易工作。您将再次遇到相同的异常。所以你应该避免从NSArray派生。

可以做的是添加一个类别来为所有NSArray 实例添加方法。

【讨论】:

    【解决方案2】:

    NSArrayclass cluster (link to Apple's documentation)。这意味着当您尝试创建NSArray 时,系统会创建NSArray 的一些私有子类。 NSArray 类只是定义了一个接口; NSArray 的子类提供接口的实现。

    您可以编写自己的NSArray 子类,但您必须为数组中的对象提供自己的存储空间。您必须自己初始化该存储。错误消息通过说您需要在子类中覆盖 initWithObjects:count: 来告诉您这一点。您的覆盖需要将对象放入您作为类实现的一部分分配的任何存储中。

    可变参数initWithObjects: 方法的NSArray 实现只是initWithObjects:count: 的包装,因此您不必实现initWithObjects:

    【讨论】:

    • 另外,在编写自己的NSArray 子类之前,请确保您阅读并理解 NSArray Class Reference 的“子类化注释”部分。
    【解决方案3】:

    您需要分配自我,并调用您的超类的 init 方法。

    if (self = [super initWithObjects:...]) {
       ...
    }
    
    return self;
    

    【讨论】:

    • 确实如此,但是具体子类化 NSArray 也有特殊的规则。
    【解决方案4】:

    也许

    self = [super initWithObjects:...];
    

    【讨论】:

    • 确实如此,但是具体子类化 NSArray 也有特殊的规则。
    • 是的。好吧,尽管如此,我还是会留下答案。第一件事。
    【解决方案5】:

    NSArray 不支持以这种方式进行子类化。不过,您可以添加一个类别,尽管这不是普遍推荐的。

    请参阅Objective C - Subclassing NSArray 了解更多想法。

    【讨论】:

    • 我改为 self = [self initWithObjects: 但这没有帮助。
    • 我想这可能是 [NSArray alloc] 实际上并没有分配一个 NSArray 所以当我这样做时,没有实现。帮助!但是为什么它会继续 initWithObjects:count: ?
    • 你为什么认为你需要继承 NSArray 呢?除非您正在建立一个专门的后备商店,否则这通常不是一个好方法。
    猜你喜欢
    • 1970-01-01
    • 2020-07-14
    • 1970-01-01
    • 1970-01-01
    • 2020-06-22
    • 2018-08-22
    • 2011-06-09
    • 2010-10-09
    • 2014-01-28
    相关资源
    最近更新 更多