我创建了一个NSArray实例,而其类不是NSArray而是__NSArrayI?

时间:2016-08-18 13:14:55

标签: objective-c nsarray class-cluster

我有以下代码:

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的子类。我错了吗?

编辑:谢谢你的所有答案。但我的问题正是为什么我在这两个案例中得到不同的结果,如果它应该有助于“阶级集群”的事务?

6 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:3)

  编辑:谢谢你的所有答案。但是我的问题正是为什么我在这两种情况下会得到不同的结果,如果它应该对#34;类集群的事务做出贡献"?

因为测试代码完全不同。您正在调用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指针,它告诉调度程序使用哪组方法。因此,您将获得实际的as-instantiated类对象(__NSArrayI)。

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

答案 2 :(得分:1)

__ NSArrayI是一个不可变数组的代码字 - 也就是说,"常规"你无法改变的NSArray。

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

答案 3 :(得分:1)

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

的子类

+ arrayWithObjects:会返回__NSArrayI,您无法对其进行任何操作,因为这是您无法用于应用商店分发的私有API。

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

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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