免费开源的iOS开发学习平台

Runtime简介:1-基础知识

Objective-C 的 Runtime 是一个运行时库(Runtime Library),它是一个主要使用 C 和汇编写的库,为 C 添加了面向对象的能力并创造了 Objective-C。直白来说,Objective-C是提供给程序员使用的语言,而Runtime是面向计算机的语言,在应用编译执行时,Objective-C会被“翻译”成Runtime进行执行。

Runtime中的一些概念

在介绍Runtime之前,需要先简单介绍一下Runtime中常见的一些概念。

  • 类Class:对于面向对象编程来说,我们常说的对象一般都是指实例化之后的对象,例如,当我们执行如下语句后,就会得到一个person对象。除此之外,类Class也是一个对象,我们称为类类型的对象(这也就可以理解为什么类方法是直接由类来调用的,或者准确来说,类方法是发送给类对象的消息)。在objc_class结构体中,我们可以获得这个类定义的所有实例变量ivars、方法列表、协议列表(如下所示)。
Person *person =[[Person alloc] init];
struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
}
  • 选择器SEL:用于标识一个在某个对象上执行的 Objective-C 方法(Method),可以简单理解为是方法列表中其中一个方法的标识符
  • 消息:消息机制是Objective-C中的重要特征,当需要某个对象执行一个方法时,其本质是给该对象发送了一条包含方法名称的消息,对象会在自己的方法列表或父类的方法列表中找到指向该方法的指针,继而找到方法的具体实现
  • IMP:指向方法实现的函数指针,由编译器生成。

准备工作

我们首先创建一个Person类,并添加如下的属性和方法。

  • Person.h文件
#import <Foundation/Foundation.h>
@interface Person : NSObject <NSCoding,NSCopying>
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) CGFloat height;
+(instancetype) person;
-(void)run;
-(void)sleep;
@end
  • Person.m文件
#import "Person.h"
@implementation Person
+(instancetype) person{
    Person *p = [[Person alloc] init];   
    return p;
}
-(void)run{
    NSLog(@"person run!");
}
-(void)sleep{
    NSLog(@"person sleep!");
}
@end

获取类中定义的属性

/*获得Person类属性名称*/
void getPropertyList () {
    unsigned int count = 0;
    objc_property_t *propertyList = class_copyPropertyList([Person class], &count);
    for (unsigned int i=0; i<count; i++) {
        objc_property_t property = propertyList[i];
        const char *propertyName = property_getName(property);
        NSLog(@"property---->%@", [NSString stringWithUTF8String:propertyName]);
    }  
}

运行结果:

获取类中定义的方法

/*获得Person类所有方法,含属性的setter/getter方法以及自定义方法*/
void getMethod () {
    unsigned int count = 0;
    Method *methodList = class_copyMethodList([Person class], &count);
    for (unsigned int i; i<count; i++) {
        Method method = methodList[i];
        NSLog(@"method---->%@", NSStringFromSelector(method_getName(method)));
    }
}

运行结果:

获取类中定义的实例变量

/*获得Person类实例变量名称(带下划线)*/
void getInstanceVariable (){
    unsigned int count = 0;
    Ivar *ivarList = class_copyIvarList([Person class], &count);
    for (unsigned int i; i<count; i++) {
        Ivar myIvar = ivarList[i];
        const char *ivarName = ivar_getName(myIvar);
        NSLog(@"Ivar---->%@", [NSString stringWithUTF8String:ivarName]);
    }
}

运行结果:

获取类遵守的协议

/*获得Person类遵守的协议*/
void getProtocol() {
    unsigned int count = 0;
    __unsafe_unretained Protocol **protocolList = class_copyProtocolList([Person class], &count);
    for (unsigned int i; i<count; i++) {
        Protocol *myProtocal = protocolList[i];
        const char *protocolName = protocol_getName(myProtocal);
        NSLog(@"protocol---->%@", [NSString stringWithUTF8String:protocolName]);
    }
}

运行结果: