NSObject.h
概述
@protocol NSObject
...
@end
对NSObject协议的定义。我们知道NSObject不仅是一个类而且是一个同名的协议。
@interface NSObject <NSObject> {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
Class isa OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop
}
...
定义NSObject类,并遵循了协议。
NSObject有一个Class类型的成员变量,点进去看文档
typedef struct objc_class *Class;
Class是一个objc_class类型的结构体指针,这个定义在objc.h中。
Class这个结构体指针都包含什么呢?
继续点进去看objc_class
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class _Nullable super_class OBJC2_UNAVAILABLE;
const char * _Nonnull name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE;
struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE;
struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE;
struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
objc_class这个结构体中有一个Class类型的isa指针。
也就是说Class是一个objc_class类型的结构体指针,其内部还有一个Class类型的指针isa。这样设计的目的是什么呢?
在objc的runtime中,类是用 objc_class 结构体表示的,对象是用 objc_object 结构体表示的。 对象的 isa 指向对象所属的类。类的isa指针指向该类的元类。
也就是说在objc_class里的isa指针指向的是该类的元类。
performSelector
//直接调用
if ([p respondsToSelector:@selector(run)]) {
[p performSelector:@selector(run) withObject:nil];
}
//可传参
if ([p respondsToSelector:@selector(speaking:)]) {
[p performSelector:@selector(speaking:) withObject:@"hello world"];
}
//带返回值
if ([p respondsToSelector:@selector(isAgirl)]) {
BOOL isGirl = [p performSelector:@selector(isAgirl) withObject:nil];
NSLog(@"%@",isGirl?@"女孩":@"男孩");
}
IMP指针使用
以Person为例:
#import <Foundation/Foundation.h>
#import "Car.h"
@interface Person : NSObject
{
NSUInteger _age;
}
@property (nonatomic, strong) Car *car;
@property (nonatomic) BOOL isGirl;
- (void)setAge:(NSUInteger)age;
- (NSUInteger)age;
- (void)run;
- (void)speaking:(NSString *)talk;
- (BOOL)isAgirl;
@end
#import "Person.h"
@implementation Person
- (void)setAge:(NSUInteger)age {
_age = age;
}
- (NSUInteger)age {
return _age;
}
- (void)run {
NSLog(@"run");
}
- (void)speaking:(NSString *)talk {
NSLog(@"speaking : %@",talk);
}
- (BOOL)isAgirl {
return self.isGirl;
}
#pragma mark - private
- (void)love {
NSLog(@"love");
}
- (Person *)lover {
return [[Person alloc] init];
}
@end
// 调用无参无返回值方法
//创建SEL
SEL runSEL = @selector(run);
//或者使用如下方法
SEL speaSEL = NSSelectorFromString(@"speaking:");
SEL isGirlSEL = NSSelectorFromString(@"isAgirl");
IMP runIMP = [p methodForSelector:runSEL];//获取IMP指针
void (*runFunction)(id, SEL) = (void *)runIMP;//定义runFunction函数,函数地址指向IMP指针所在的地址
runFunction(p, runSEL);//调用runFunction函数
//使用这种方式可以调用私有方法
//调用私有方法,返回一个Person类型的返回值
SEL loverSEL = NSSelectorFromString(@"lover");
IMP loverIMP = [p methodForSelector:loverSEL];
id (* giveLover)(id, SEL) = (void *)loverIMP;
Person *lover = giveLover(p,loverSEL);
NSLog(@"my lover : %@",lover);
//传参
SEL speakSEL = @selector(speaking:);
IMP speakIMP = [p methodForSelector:speakSEL];
//IMP speakIMP = [Person instanceMethodForSelector:speakSEL];
void (* speakIng)(id,SEL,NSString *) = (void *)speakIMP;
speakIng(p,speakSEL,@"hello world");
判断方法
Person *p = [[Person alloc] init];
Car *car = [[Car alloc] init];
//判断是否继承自NSObject,返回NO表示继承自NSObject
if (![p isProxy]) {
//继承自NSObject
}
if (![Person isProxy]) {
//继承自NSObject
}
//判断两个对象是否相等,这里应该判断的是内存地址吧
if ([p isEqual:car]) {
NSLog(@"equal");
}
//判断p是否是NSObject类或者NSObject的子类对象
if ([p isKindOfClass:[NSObject class]]) {
NSLog(@"NSObject class");
}
//判断p是否是Person类的对象
if ([p isMemberOfClass:[Person class]]) {
NSLog(@"isMemberOfClass Person");
}
//判断p是否遵循NSObject协议
if ([p conformsToProtocol:@protocol(NSObject)]) {
}
// 判断对象是否能够调用给定的方法
if ([p respondsToSelector:@selector(setAge:)]) {
}
// 判断Person类的实例是否能够调用给定的方法
if ([Person instancesRespondToSelector:@selector(setAge:)]) {
}
其他方法
关于其他方法的使用这里不一一赘述。