系列文章目录
iOS基础—Block
iOS基础—Protocol
iOS基础—KVC vs KVO
iOS网络—AFNetworking
iOS网络—NSURLSession
iOS内存管理—MRC vs ARC
iOS基础—Category vs Extension
iOS基础—多线程:GCD、NSThread、NSOperation
iOS基础—常用三方库:Masonry、SDWebImage
iOS基础—定时器:GCD、NSTimer、CADisplayLink
一、Category
1.Category是什么
Category(类别)是Objective-C 2.0之后添加的语言特性,允许开发者在不修改原有类的情况下,为其添加新的方法。Category 特殊实用于扩展系统类和第三方类的功能。
我们在利用Xcode 创建文件时,可以将 File Type 指定为 Category,Class指定为我们要举行扩展的类:
然后就会自动天生 Person+Student.h 和 Person+Student.m 文件:
2. 利用场景
利用 Category 的好处是:
- 分离代码逻辑
Category 可以将一个类的实现分成多个独立的部门,每个部门专注于差别的功能或逻辑。这使得代码更易于管理和维护。
- 扩展现有类
Category 允许你为现有的类添加新功能,而无需子类化或修改原始类的代码。这对于扩展系统类(如 NSString, NSArray 等)尤其有效。
- 组织代码
通过利用 Category,可以将相关的方法组织在一起,使代码更加模块化和易读。比方,可以为一个复杂的视图控制器创建多个 Category,每个 Category 处理视图控制器的差别方面。
- 简化代码重用
Category 允许你在多个类中重用相同的代码,而无需复制粘贴。这对于通用的工具方法或功能特殊有效。
- 动态加载功能
Category 可以在运行时动态加载功能,这使得它们非常恰当插件系统或模块化应用。
如果我们创建一个 MacOs 的 Command Line Tool 程序用 Category 对类举行扩展,会报错:
/Applications/code_test/category_test/main.m:17:14 No visible @interface for ‘Person’ declares the selector ‘PrintNameTwice’
这是由于 Command Line Tool 程序中函数的调用是编译时确定的,而 Category 是 Runtime 时加载的,以是我们创建一个 App 程序举行实行:
3.注意事项
分类只能增加方法,不能增加成员变量。
分类中的方法如果与原类的方法名相同,大概会覆盖原类的方法。
可以添加属性声明,但不能直接实现属性的存取方法(getter 和 setter)。关联对象(Associated Objects)是一种机制,允许为现有对象动态添加属性。它们利用 objc_setAssociatedObject 和 objc_getAssociatedObject 函数来设置和获取值。
在Objective-C中,属性(Property)通常由实例变量(Instance Variables)和访问方法(Getter和Setter)构成。当你在类的声明中添加一个属性时,编译器会自动天生相应的实例变量和访问方法。然而,在Category中,编译器无法为其添加实例变量,由于Category并不改变类的内存结构。
objc_setAssociatedObject 和 objc_getAssociatedObject 的函数原型:
- void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
- //object: 需要关联值的对象。
- //key: 用于唯一标识关联的键,通常使用静态地址或唯一的指针。
- //value: 要关联的值,可以是任何对象。如果传入 nil,则会移除先前关联的值。
- //policy: 关联策略,定义了关联对象的内存管理语义。
- OBJC_ASSOCIATION_ASSIGN:指定一个弱引用关联对象,不保留新的值。
- OBJC_ASSOCIATION_RETAIN_NONATOMIC:指定关联对象的强引用,且不使用原子操作。
- OBJC_ASSOCIATION_COPY_NONATOMIC:指定关联对象的副本,且不使用原子操作。
- OBJC_ASSOCIATION_RETAIN:指定关联对象的强引用,使用原子操作。
- OBJC_ASSOCIATION_COPY:指定关联对象的副本,使用原子操作。
- id objc_getAssociatedObject(id object, const void *key);
- //object: 需要获取关联值的对象。
- //key: 用于唯一标识关联的键,这个键必须与 objc_setAssociatedObject 时使用的键相同。
复制代码 对于原理,美团技能团队已经做了深入的解说:深入理解Objective-C:Category
二、Extension
在 iOS 开发中,类扩展(Class Extension)是一种用于在类的实现文件中声明私有方法和属性的机制。与 Category 差别,类扩展只能在类的实现文件中利用,而且必须在编译时确定。类扩展通常用于声明类的私有接口,隐藏实现细节,增强封装性。
类扩展的用途:
- 声明私有属性:在类扩展中声明的属性只能在类的实现文件中访问。
- 声明私有方法:在类扩展中声明的方法只能在类的实现文件中调用。
- 提供更好的封装:通过将私有接口隐藏在实现文件中,类扩展进步了代码的封装性。
下面是一段在 MyClass.m 文件中对 MyClass 类举行扩展的代码:
- // MyClass.m
- #import "MyClass.h"
- @interface MyClass ()
- @property (nonatomic, strong) NSString *privateProperty; // 私有属性
- - (void)privateMethod;// 私有方法
- @end
- @implementation MyClass
- - (void)privateMethod {
- NSLog(@"Private Property: %@", self.privateProperty);
- }
- @end
复制代码 三、对比
- 用于为现有类添加方法,而不需要修改原始类的代码。
- 可以在任何地方定义和利用。
- 主要用于将类的功能模块化、分离代码逻辑,或者为系统类添加新功能。
- 用于在类的实现文件中声明私有属性和方法。
- 只能在类的实现文件中利用。
- 主要用于隐藏实现细节,增强类的封装性。
- 只能添加方法,不能添加实例变量(成员变量)。
- 可以添加属性声明,但不能直接实现属性的存取方法(getter 和 setter)。
- 可以添加方法和实例变量(成员变量)。
- 可以添加属性,而且可以在实现文件中实现属性的存取方法。
- 在运行时加载,可以动态地为类添加方法。
- 方法的加载次序大概影响方法的覆盖(如果多个 Category 添加了相同的方法)。
- 在编译时确定,必须在类的实现文件中定义。
- 由于是在编译时确定的,类扩展中的方法和属性与类的其他部门一样被处理。
- 方法是公共的(public),可以被任何地方访问。
- 实用于对外扩展类的功能。
- 方法和属性是私有的(private),只能在类的实现文件中访问。
- 实用于隐藏实现细节,增强封装性。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |