大家好,我是OB!
今天结合源码来看看NSObject常用方法
首先声明两个类,
Animal
,Dog
,继承关系如下
@interface Animal: NSObject
@interface Dog: Animal
1、 [Dog class]
和[dog class]
一样吗?
新手还在看,老手已经开始
NSLog
了。
结果是一样的。看看源码就清楚了,
+ (Class)class {
return self;
}
- (Class)class {
return object_getClass(self);
}
这里要清楚三个概念,实例对象,类对象,元类对象。
我们创建的实例对象所拥有的实例方法,类方法,分别存储在类对象,元类对象。而 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;
}
打上断点,输入指令可以看到,
dog
的isa
指向了类对象dogClass
,而 类对象dogClass
的isa
指向了元类对象dogMetaClass
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
这里是对
runtime
的objc_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
,而实例方法中的self
是dog
而 [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是常量,她们的内存地址一样哦。
今天先到这里!大家好我是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