前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OC基础Category和Extension区别

OC基础Category和Extension区别

作者头像
Light413
发布2020-04-08 16:10:47
1.5K0
发布2020-04-08 16:10:47
举报

Category 和 Extension介绍

Category
  • 可以给当前已知的类添加方法(类方法和实例方法),这个类可以是自定义的类,也可以是系统自带的类。当添加的方法和类的原有方法重名时,会‘覆盖’类的原有方法.

原类的方法还是存在的,并不是真的给覆盖了。因为在运行时当给对象发消息,会根据对象的‘isa’指针找到所属的类,然后在类的方法列表中根据方法名寻找,当找到第一个就返回了,而通过category添加的方法又在方法列表的最上面所以没有机会找到类原来方法`。

  • 可以通过property添加属性,但也只是对属性的set、get方法声明,没有实现,也不能生成带下划线的变量。
  • 不能添加成员变量。注意,通过runtime 关联对象添加的不叫属性,也不叫成员变量,它和当前类没有根本上的关系,只是仅仅的连在了一起。
Extension
  • 可以给一个已知的类添加方法(类方法和实例方法),这个类只能是自定义的类,不可以是系统自带的类,因为不能得到.m文件。由于在已知的类.m 中操作所以可以对外界隐藏一些方法或变量,使其成为私有。
  • 可以添加属性和成员变量,也可以为属性生成set、get方法和默认的实现。通过extension添加的方法和变量真的成为了当前类的一部分。

不同之处

eg:分别给自定义的User类添加Category,Extension

代码语言:javascript
复制
//Category
@interface User (InnterAdd)
-(void)test;
@end
@implementation User (InnterAdd)

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

@end

//Extension
@interface User ()

@property (copy)NSString * addr;

@end

表现形式上,Category有名称,有自己的.m文件,extension没有名称看起来像个匿名的分类,没有.m文件。 Category也可以没有名称,这样两者在表现上就一样了。

Category: 是在运行时加载处理的,这个过程中把添加的方法添加到类的方法列表中,由于类的内存结构布局是在编译时期确定的,所以在运行时不能再添加实例变量否则就破坏了内存结构(访问非法内存地址存在不可预知的错误,所以是禁止的)。那为啥能添加方法而不能添加成员变量呢?在runtime层,category用结构体category_t(在objc-runtime-new.h中可以找到此定义)如下:

代码语言:javascript
复制
typedef struct category_t {
    const char *name;
    classref_t cls;
    struct method_list_t *instanceMethods;
    struct method_list_t *classMethods;
    struct protocol_list_t *protocols;
    struct property_list_t *instanceProperties;
} category_t;

从中可看出可以添加实例方法,类方法,甚至可以实现协议,添加属性。没有表示实例变量的存贮。

其实分类本身而言它就不是一个类,分类,分开类的一部分操作,就是一个在运行时给主类添加方法、属性、或者协议的操作或者对外提供的一种接口扩展,在分类中添加方法直接绑定到主类原有的方法列表。所以感觉把分类这个名字改为方法扩展更容易理解(o)/~,所以在这一点来看,Category和Extension在目的上还是一致的,都是对原有的类增加新的操作。

Extension:在编译时处理的,添加的变量和方法和类密切的在一起,就是类的一部分,类消失它也消失。

Category中关联对象

runtime提供了以下三个方法

代码语言:javascript
复制
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
objc_getAssociatedObject(id object, const void *key)
void objc_removeAssociatedObjects(id object)

其中objc_removeAssociatedObjects 移除已添加的所有对象,所以实际操作要注意别把其他地方添加的关联也给remove了。所以还是通过objc_setAssociatedObject 直接置为nil更为可靠。

#END

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Category 和 Extension介绍
  • 不同之处
  • Category中关联对象
  • #END
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档