NSObject.h

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:)]) {
    
}

其他方法

关于其他方法的使用这里不一一赘述。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Morris_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值