【问题标题】:I created an instance of NSArray, whereas whose class is not NSArray but __NSArrayI?我创建了一个 NSArray 的实例,而它的类不是 NSArray 而是 __NSArrayI?
【发布时间】:2016-08-18 13:14:55
【问题描述】:

我有以下代码:

id anArray = [NSArray arrayWithObjects:@1, @2, nil];
NSLog(@"anArrayClass - %@", [anArray class]);
NSLog(@"NSArrayClass - %@", [NSArray class]);

我希望两个输出都是NSArray,但是输出结果是:

2016-08-18 21:08:53.628 TestUse[9279:939745] anArrayClass - __NSArrayI
2016-08-18 21:08:53.629 TestUse[9279:939745] NSArrayClass - NSArray

然后我创建一个名为CAJTestClass 的测试类并创建该类的一个实例:

id testInstance = [CAJTestClass new];
NSLog(@"testInstanceClass - %@", [testInstance class]);
NSLog(@"cajTestClass - %@", [CAJTestClass class]);

这次的输出变成:

2016-08-18 21:08:53.629 TestUse[9279:939745] testInstanceClass - CAJTestClass
2016-08-18 21:08:53.629 TestUse[9279:939745] cajTestClass - CAJTestClass

这一次的结果是我所期望的。但是为什么[anArray class] 会成为__NSArrayI
“Effective Objective-C”的解释是NSArray 是“类集群”的一部分(我认为这是一系列具有继承关系的类)。但CAJTestClass 也是NSObject 的子类。我错了吗?

编辑:感谢您的所有回答。但我的问题是,如果它应该有助于“类集群”的事务,为什么我会在这两种情况下得到不同的结果?

【问题讨论】:

    标签: objective-c nsarray class-cluster


    【解决方案1】:

    编辑:感谢您的所有回答。但我的问题是,如果它应该有助于“类集群”的事务,为什么我会在这两种情况下得到不同的结果?

    因为测试代码完全不同。您正在调用一个返回NSArray 子类的NSArray 方法,但您正在调用[CAJTestClass new],它返回CAJTestClass 本身。如果你让它们相同,那么你会得到相同的结果:

    @interface CAJTestClass : NSObject
    + (instancetype)testClassWithMagic;
    @end
    
    @interface __MagicTestSubclass : CAJTestClass
    @end
    
    @implementation CAJTestClass
    
    + (instancetype)testClassWithMagic {
        return [__MagicTestSubclass new];
    }
    @end
    
    @implementation __MagicTestSubclass
    @end
    

    现在使用您的测试代码:

        id testInstance = [CAJTestClass testClassWithMagic];
        NSLog(@"testInstanceClass - %@", [testInstance class]);
        NSLog(@"cajTestClass - %@", [CAJTestClass class]);
    
    2016-08-18 09:57:15.126 test[72004:47882338] testInstanceClass - __MagicTestSubclass
    2016-08-18 09:57:15.127 test[72004:47882338] cajTestClass - CAJTestClass
    

    rmaddy 提出了您有不同问题的可能性,他可能是正确的,所以我也会回答那个问题。

    [anArray class] 是将-class 消息传递给实例anArray 的结果。当实例接收到-class 消息时,通常要做的事情是返回它被初始化为的特定类(它的特定子类)。这不是通用的(KVO 类故意打破了这个规则,甚至可以在运行时更改类),但它是常见的方法。这是结构中的isa 指针,它告诉调度程序使用哪组方法。所以你得到了实际的实例化类对象 (__NSArrayI)。

    [NSArray class] 是将+class 消息传递给类对象NSArray 的结果。类对象的通常做法是返回self(我不知道有任何类违反了该规则;违反该规则可能是不合法的)。这样你就得到了你将消息传递给 (NSArray) 的类。

    【讨论】:

    • 我认为 OP 想知道为什么 [anArray class][NSArray class] 返回不同的结果。
    • 这是最初的问题(并且在所有其他答案中都得到了很好的回答),但编辑进一步询问为什么这是NSArray 的一种方式,而CAJTestClass 的另一种方式。原因是CAJTestClass 的情况与NSArray 的代码完全不同。
    • 不,没有一个答案可以解释为什么两者不同。这一切都解释了__NSArrayI 是什么。
    • 我对这个答案没有什么要补充的。但我认为 OP 认为 NSArray 和 CAJTestClass 的结果应该是相同的,因为它们都继承自 NSObject。关键是你从类集群工厂返回的所有类都继承自同一个基类:所以你总是会从 NSArray 类集群中获得一个 NSArray 子类,依此类推。
    • 感谢您的回答。为了更清楚起见,NSArray 是否被视为其类集群中的基本抽象类?
    【解决方案2】:

    在您的软件开发中,您唯一担心的类是 NSArray 和 NSMutableArray。在幕后,有许多不同的班级。例如,空数组的单例类。具有一个数组元素的数组的类。所有这些都节省了内存,因为人们使用了大量的琐碎数组。

    【讨论】:

    • 我单独投票支持这个答案,因为它提到了“幕后”。要点是NSArray arrayWithObjects: 被允许返回任何实现NSArray 接口的东西。你的代码永远不应该关心它具体得到了什么类。 “类集群”通常用于表示您从初始化或工厂方法返回的内容不必是您分配或使用工厂方法的类的类型。通常它是一个子类。
    【解决方案3】:

    __NSArrayI 是不可变数组的代码字 - 即您无法更改的“常规” NSArray。

    __NSArrayM 是可变数组的代码字 - 即 NSMutableArray。在 NSMutableArray 中,您可以添加和删除项目。

    【讨论】:

      【解决方案4】:

      __NSArrayI 是不可变 NSArray 的私有类。还有__NSArrayM,它是一个可变数组的私有类。两者都是NSArray的子类

      + arrayWithObjects: 返回一个__NSArrayI,您无能为力,因为这是您无法用于应用商店分发的私有 API。

      如果你想检查你的对象是NSArray,你可以使用

      if ([anArray isKindOfClass:[NSArray class]]){
           //blablabla
      }
      

      【讨论】:

        【解决方案5】:

        __NSArrayI 指的是数组的不可变版本,初始化后无法更改。

        【讨论】:

          【解决方案6】:

          __NSArrayI 表示 NSArray 的不可变形式。还有 __NSArrayM,它是可变形式。不可变的意思是你不能改变它,这个数组里面的对象不能改变。对于可变的,您可以更改元素。你也可以看看这个帖子。我想这也回答了你的问题。 What is __NSArrayI and __NSArrayM? How to convert to NSArray?

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-02-22
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多