Objective-C:关于class方法的使用注意

437 阅读2分钟

关于使用[object class] == [Object class]判断某个对象是否是某个类的实例时所需要注意的问题

该写法是否有效?

  1. 简单创建Person类

     // .h
     @interface Person : NSObject
     @end
    
     // .m
     @implementation Person
     @end
    
  2. 使用Person打印验证[object class] == [Object class]的有效性

     Person *person = [[Person alloc] init];
     NSLog(@"%@ - %p", [person class], [person class]);
     NSLog(@"%@ - %p", [Person class], [Person class]);
    
     BOOL result = [person class] == [Person class];
     NSLog(@"%@", result ? @"YES" : @"NO");
    
  3. 得到打印:

     Person - 0x1000020e0
     Person - 0x1000020e0
     YES
    

通过上面的验证,似乎[object class] == [Object class]确实可以用来判断某个对象是否是某个类的实例。但当我们不加思考就使用该写法时,会发生什么问题呢?让我们看看下面的例子:

  1. 使用NSString打印验证[object class] == [Object class]的有效性

     NSString *string = @"string";
     NSLog(@"%@ - %p", [string class], [string class]);
     NSLog(@"%@ - %p", [NSString class], [NSString class]);
    
     BOOL result = [string class] == [NSString class];
     NSLog(@"%@", result ? @"YES" : @"NO");
    
  2. 猜猜打印?

     __NSCFConstantString - 0x7fff8537b8e0
     NSString - 0x7fff858f5178
     NO
    

    此时我们可以观察到结果出现了不一致。为什么呢?

  3. 分析

    读过《Effective Objective-C 2.0》(第九条)的小伙伴应该可以反应过来__NSCFConstantStringNSString之间的关系——类簇。没错,在OC中通过某个类创建的实例不一定就是该类的实例,它也可能是某个被系统隐藏的类的实例。不止是NSString如此,NSArray等一系列容器类以及自定义的类簇也可能会发生该问题。

  4. 解决方案

    如果意识到所判断的类内部可能是类簇的实现时,建议使用[object isKindOfClass: [Object class]]来判断是否属于该类的继承体系。

    这里也不能使用[object isMemberOfClass: [Object class]],因为该对象不是该类的直接实例。