美文网首页
iOS-分类(Category)

iOS-分类(Category)

作者: 丁勒个东 | 来源:发表于2020-02-25 19:28 被阅读0次

在iOS开发中我们常使用Category来给类添加方法或者属性,原理是什么呢.

分类概况

我们先尝试写个分类.
NSObject+Category.h

#import <Foundation/Foundation.h>
#import<UIKit/UIKit.h>

@protocol protocol  <NSObject>

-(void)protocolMethod;

@end

@interface NSObject (Category)<protocol>

@property(nonatomic,strong)NSString *property;

+(void)classMethod;

-(void)instanceMethod;

@end

NSObject+Category.m

#import "NSObject+Category.h"

@implementation NSObject (Category)
+(void)classMethod{
    NSLog(@"classMethod");
}

-(void)instanceMethod
{
    NSLog(@"instanceMethod");
}

@end

我们先通过clang命令将其转化为C++文件查看其中的编译过程

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc NSObject+Category.m

执行后会在当前文件家中生成cpp文件.在cpp文件中可以查看到分类的结构体

static struct _category_t _OBJC_$_CATEGORY_NSObject_$_Category __attribute__ ((used, section ("__DATA,__objc_const"))) = 
{
    //所属类的类名  
    "NSObject",
    //要扩展的类对象,编译期间是不会定义的,而是在Runtime阶段通过name对 应到对应的类对象
    0, // &OBJC_CLASS_$_NSObject,
    //category中所有给类添加的实例方法的列表
    (const struct _method_list_t *)&_OBJC_$_CATEGORY_INSTANCE_METHODS_NSObject_$_Category,
    //category中所有添加的类方法的列表
    (const struct _method_list_t *)&_OBJC_$_CATEGORY_CLASS_METHODS_NSObject_$_Category,
    //协议列表
    (const struct _protocol_list_t *)&_OBJC_CATEGORY_PROTOCOLS_$_NSObject_$_Category,
    //category中所有添加的属性列表
    (const struct _prop_list_t *)&_OBJC_$_PROP_LIST_NSObject_$_Category,
};

分类属性

在结构体中有所属类名/类的对象/实例方法列表/类方法列表/协议列表/属性列表,但是没有成员变量列表.在OC的类中申明一个属性,都会自动生成一个带"_"的成员变量并创建setter/getter方法,分类中没有成员变量列表,所以在分类中创建的属性仅仅是一个申明,并没有对应的成员变量以及setter/getter方法,如果直接使用分类中的属性在运行时会报错.但是OC是一门动态语言,系统虽然没有处理,但是我们可以通过runtime在分类中手动添加setter/getter方法.

#import "NSObject+Category.h"
#import <objc/runtime.h>

@implementation NSObject (Category)

+(void)classMethod{
    NSLog(@"classMethod");
}

-(void)instanceMethod
{
    NSLog(@"instanceMethod");
}

//定义一个key值
static NSString *propertyKey = @"propertyKey";
//运行时实现setter方法
- (void)setProperty:(NSString *)property{
        objc_setAssociatedObject(self, &propertyKey, property, OBJC_ASSOCIATION_COPY);
}
//运行时实现getter方法
- (NSString *)property {
    return objc_getAssociatedObject(self, &propertyKey);
}
@end

这样就可以在运行过程中来获取和设置分类的值.需要注意的是,以上代码只是实现了setter/getter方法,并有创建成员变量,所以直接使用_成员变量,依然会报错.

分类方法

我们知道在OC中调用方法时,首先通过obj的isa指针找到obj对应的class(类方法是metaClass)。在class中,有一块最近调用的方法的指针缓存,所以先去cache通过selector查找对应的method,若cache中未找到,再去method list中查找,若method list中未找到,则去superClass中查找。若能找到,则将method加入到cache中,并通过method中的函数指针跳转到对应的函数中去执行。整个过程中并不会到分类的methodList中查找.那分类中的方法是如何被调用到的呢.
这要理解分类的加载栈

_objc_init
└──map_2_images
    └──map_images_nolock
        └──_read_images

_objc_init 算是整个 objc4 的入口,进行了一些初始化操作,注册了镜像状态改变时的回调函数;
map_2_images 主要是加锁并调用 map_images_nolock;
map_images_nolock 在这个函数中,完成所有 class 的注册、fixup等工作,还有初始化自动释放池、初始化 side table 等工作并在函数后端调用了 ;
_read_images _read_images 方法干了很多苦力活,比如加载类、Protocol、Category,加载分类的代码就写在 _read_images 函数的尾部;

简单的来说,就是初始化时,会先注册镜像,这个镜像会完成class的注册,并通过read_images把category的实例方法、协议以及属性添加到类上,把category的类方法和协议添加到类的metaclass上.

添加方法列表的时候是后添加的在新形成的列表前部,这也是为什么在有多个category中有同名方法时,后编译的在调用时会“覆盖”前面已编译的方法。其实方法本身并没有被覆盖,只是调用的时候是从上而下查找方法列表,当运行时找到对应的方法名后就去忙着调用了,并不会管后面的同名方法。

如果多个分类中有同名方法,可以在Build Phases->Compile Sources中移动文件位置.最终执行的是最后加载的.

总结

分类可以在不改变类名和原类的实现的前提下,进行类的扩展.支持开发人员针对自己构建的类,把相关的方法分组到多个单独的文件中,针对大型而复杂的类,可以提高维护性和可读性,并简化单个源文件的管理,在日常的开发中是非常强大的。

相关文章

  • 2-1 分类 类后面加括号

    1.什么是分类 = 类别。通过runtime将方法添加进 类里面 iOS-分类(Category)[https:...

  • iOS-Category原理

    参考篇:iOS-分类(Category) 前言:本文简述Category原理,如有错误请留言指正。 第一部分:有关...

  • iOS-分类(Category)

    Category是Objective-C 2.0之后添加的语言特性,分类、类别其实都是指的Category。Cat...

  • iOS-分类(Category)

    在iOS开发中我们常使用Category来给类添加方法或者属性,原理是什么呢. 分类概况 我们先尝试写个分类.NS...

  • iOS-分类 Category

    Category(objc_category) Category是表示一个指向分类的结构体的指针,其定义如下: 分...

  • iOS-底层-Category分类

    iOS中的Category我们经常使用,主要是给一些类添加新的方法,或者拆分类。进行方法调用的时候,如果调用的是写...

  • iOS 开发:Runtime(详解四)Category

    1. Category (分类)简介 1.1 什么是 Category(分类)? Category(分类)主要作用...

  • AVPlayer音乐锁屏功能

    [iOS]iOS AudioSession详解 Category选择 听筒扬声器切换iOS- 关于AVAudioS...

  • iOS基础总结理解及相关面试题

    iOS基础 分类(Category)和类扩展(Class Extension)分类(Category)Catego...

  • 分类(Category)与类拓展(Extension)

    分类(Category) 1.分类(Category)是什么? 分类是oc特有的语法,表示指向分类的结构体指针。分...

网友评论

      本文标题:iOS-分类(Category)

      本文链接:https://www.haomeiwen.com/subject/icvxchtx.html