匿名分类

737 阅读2分钟

匿名分类

匿名分类,extension,也叫类扩展,是为了给当前的类扩充私有成员变量、属性或者方法。它有两种实现方式,第一种是写在.m文件中;第二种是实现一个extension.h文件。

1. .m文件中实现

首先,我们先按照第一种方法实现,给TPerson添加了匿名分类,添加了一个名为extendProp的属性,一个名为extendMethod的方法。

@interface TPerson : NSObject

@property (nonatomic, copy) NSString *name;

- (void)sayHello;
+ (void)sayYo;

@end


#import "TPerson.h"

@interface TPerson()

@property (nonatomic, copy) NSString *extendProp;

- (void)extendMethod;

@end


@implementation TPerson

+ (void)load {
    NSLog(@"类-load");
}

- (void)sayHello {
    NSLog(@"%s",__func__);
}

+ (void)sayYo {
    NSLog(@"%s",__func__);
}

- (void)extendMethod {
    NSLog(@"%s",__func__);
}

@end

那么匿名分类的数据是什么时候添加到类中的呢,我们知道类的加载有一个重要的方法:read_images,我们在这个方法中添加以下代码,进行调试:

void _read_images(header_info **hList, uint32_t hCount, int totalClasses, int unoptimizedTotalClasses) {

    ......
    
        for (EACH_HEADER) {
        classref_t *classlist = 
            _getObjc2NonlazyClassList(hi, &count);
        for (i = 0; i < count; i++) {
            Class cls = remapClass(classlist[i]);
            if (!cls) continue;

            const char *cname = cls->nameForLogging();
            const char *oname = "TPerson";
            // printf("类名 :%s \n",cname);
            if (cname && (strcmp(cname, oname) == 0)) {
                printf("_read_images - _getObjc2NonlazyClassList 类名 :%s  - %p\n",cname,cls);
            }
            
            
            addClassTableEntry(cls);
            realizeClassWithoutSwift(cls);
            
            if (cname && (strcmp(cname, oname) == 0)) {
                printf("_read_images - _getObjc2NonlazyClassList 类名 :%s  - %p\n",cname,cls);
            }
        }
    }

}

realizeClassWithoutSwift上方的printf的地方设置个断点,进行LLDB调试:

此处可以看到类并没有加载完成,ro中没有数据。

然后在realizeClassWithoutSwift下方的printf的地方设置个断点,进行LLDB调试:

此时,可以看到匿名分类中的方法和属性都已经写入到ro中,上述代码,匿名分类和类是一起在realizeClassWithoutSwift方法中加载的。

2. 写成extension.h文件

我们创建一个名为TPerson+mExtension.h的文件,文件内容如下,

@interface TPerson ()

@property (nonatomic, copy) NSString *sigleExtProp;

@end

当在TPerson.m中引用这个文件,就可以使用了。

总结

匿名分类是用来扩充类的私有属性、方法、协议的。在编译期,和类一起编译、加载的。其信息也会加载到类的ro中。