NSObject常用方法superclass,[super superclass],isMemberOfClass,isKindOfClass,isEqual,clang

大家好,我是OB!

今天结合源码来看看NSObject常用方法

首先声明两个类,AnimalDog,继承关系如下

@interface Animal: NSObject
@interface Dog: Animal
1、 [Dog class][dog class]一样吗?

新手还在看,老手已经开始NSLog了。
结果是一样的。看看源码就清楚了,

+ (Class)class {
    return self;
}

- (Class)class {
    return object_getClass(self);
}

这里要清楚三个概念,实例对象,类对象,元类对象。

isa1

我们创建的实例对象所拥有的实例方法,类方法,分别存储在类对象,元类对象。而 object_getClass就是获取self的类对象。

通过一个案例证实以上不是瞎说

struct ob_objc_class {
    Class isa;
};
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Dog *dog = [[Dog alloc] init];
       
        Class personClass = [dog class];
        struct ob_objc_class * personClass1 = (__bridge struct ob_objc_class *)(personClass);
        
        Class personMetaClass = object_getClass(personClass);
           }
    return 0;
}

打上断点,输入指令可以看到,dogisa指向了类对象dogClass,而 类对象dogClassisa指向了元类对象dogMetaClass

isa2

2、super

Dog 的init中,下面打印什么?

- (instancetype)init{
    self = [super init];
    if (self) {
        NSLog(@"%@",[self class]);
        NSLog(@"%@",[super class]);
        NSLog(@"%@",[self superclass]);
        NSLog(@"%@",[super superclass]);
    }
    return self;
}

打印结果

 Test_01[28917:2075877] Dog
 Test_01[28917:2075877] Dog
 Test_01[28917:2075877] Animal
 Test_01[28917:2075877] Animal

这里是对runtimeobjc_msgSend() objc_msgSendSuper()super关键字的理解

首先[self class][super class]编译过后会变成

objc_msgSend(self, sel_registerName("class"));
struct __rw_objc_super {
	self,
   class_getSuperclass(objc_getClass("Dog")),
};
   objc_msgSendSuper(__my__rw_objc_super,sel_registerName("class"));

最重要的是这两个方法的接受者,也就是方法调用者都是self

super关键字,表示方法查找从父类开始,直接跳过了self,但是接受者还是self,所以当他们在NSObject找到class实现时,

//NSObject中class实现
- (Class)class {
    return object_getClass(self);
}

返回的都是Dog,

同理,superClass方法也是一样,只是方法查找的起始位置不一样,实现都是一样,

+ (Class)superclass {
    return self->superclass;
}
- (Class)superclass {
    return [self class]->superclass;
}

所以返回的都是Animal

3、isMemberOfClass

类A的类型 ?类B的类型,比较同一种类,不包含子父类
观察下面代码

NSLog(@"%d",[self isMemberOfClass:[Dog class]]); //1
NSLog(@"%d",[Dog isMemberOfClass:[Dog class]]);  //0

为什么会出现这样的结果?先看看它的实现,可以看出这是只有当两个对象的类对象相等时,才能返回YES

+ (BOOL)isMemberOfClass:(Class)cls {
    return object_getClass((id)self) == cls;
}

- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}

注意类方法和实例方法中的self是不同的,类方法中的self是类对象Dog,而实例方法中的selfdog

[Dog isMemberOfClass:[Dog class]]中,相当于是object_getClass(Dog) == [Dog class];object_getClass(Dog)其实是类对象的isa指向的元类对象dogMetaClass,所有不相等,

改成如下代码就可以了

[Dog isMemberOfClass:object_getClass([Dog class])] //1
4、isKindOfClass

类A是否是类B,或者是B的子类

NSLog(@"%d",[self isKindOfClass:[Dog class]]); //1
NSLog(@"%d",[Dog isKindOfClass:[Dog class]]); //0
NSLog(@"%d",[Dog isKindOfClass:object_getClass([Dog class])]); //1

isMemberOfClass 一样,只不过是多了个for循环,因为会去父类查找。

+ (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

- (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}
5、isEqual

比较两个对象是否完全相等,比较内存地址

NSLog(@"%d",[self isEqual:[Dog class]]); // 0
NSLog(@"%d",[Dog isEqual:[Dog class]]);  // 1

先看源码,就是完全比较两边是不是完全相等,

+ (BOOL)isEqual:(id)obj {
    return obj == (id)self;
}

- (BOOL)isEqual:(id)obj {
    return obj == self;
}

所以[dog1 isEqual:dog2] 不相等,因为 dog1 != dog2

Dog *dog1 = [[Dog alloc] init];
Dog *dog2 = [[Dog alloc] init];
NSLog(@"%d", [dog1 isEqual:dog2]); //0
NSLog(@"%d", [[dog1 class] isEqual:[dog2 class]]); // 1

注意:如果是常量就不太一样了哦

NSString *s1 = @"werthjgfcdxsdfghgfdsdfg";
NSString *s2 = @"werthjgfcdxsdfghgfdsdfg";
NSLog(@"%d", [s1 isEqual:s2]); // 1

这里是相等的哦,因为s1和s2是常量,她们的内存地址一样哦。
isa3

今天先到这里!大家好我是OB!

对了,获取编译后的代码在终端指令

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc 需要编译的文件 -o 编译后的文件名
例如
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc /Users/OB/Desktop/Test_01/Test_01/main.m -o myMain.cpp

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值