0

我有以下代码:

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

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

4

6 回答 6

3

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

因为测试代码完全不同。您正在调用一个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) 的类。

于 2016-08-18T13:57:42.860 回答
3

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

于 2016-08-18T13:30:26.367 回答
1

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

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

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

if ([anArray isKindOfClass:[NSArray class]]){
     //blablabla
}
于 2016-08-18T13:31:55.117 回答
1

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

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

于 2016-08-18T13:30:36.187 回答
0

__NSArrayI 表示 NSArray 的不可变形式。还有 __NSArrayM,它是可变形式。不可变的意思是你不能改变它,这个数组里面的对象不能改变。对于可变的,您可以更改元素。你也可以看看这个帖子。我想这也回答了你的问题。__NSArrayI 和 __NSArrayM 是什么?如何转换为 NSArray?

于 2016-08-18T13:30:55.297 回答
0

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

于 2016-08-18T13:30:42.070 回答