ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Category与Extension

2021-02-09 12:31:04  阅读:191  来源: 互联网

标签:Category Extension 方法 void 扩展 NSString newString


1. Category

1.1 定义与特点

  • ObjC语言的一个灵活的类扩展机制,可以在不知道原有代码的基础上向一个已存在类添加新的方法
  • 不能修改、删除已有方法,对扩展开放、对修改封闭,体现了面向对象的OCP原则,降低了代码的耦合度。
  • 类别扩展的新方法有更高优先级,会覆盖类中已有的同名方法;声明的方法可以不实现,但不实现时不可以调用此方法

1.2 关于添加变量

  • 只能添加扩展方法,不能添加成员变量
  • 因为Category是运行期决议,运行时对象的内存布局已经确定,objc_class结构体大小已确定,无法再添加成员变量
  • Category中定义了property后,编译器只为其声明了存取方法,但没有实现;也没有合成加下划线的实例变量名,导致无法访问实例变量名

1.3 用runtime为属性添加存取方法

  1. 可以使用runtime提供的关联对象方法,动态的为property实现gettersetter,以实现setter为例
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
  • key是一个void指针
  • value是关联对象,是id类型(编译时类型不确定,视为任意Object类型)
  • policy指定一个内存管理策略来处理关联对象,
    OBJC_ASSOCIATION_ASSIGN:被关联对象释放时,关联对象不会被释放
    OBJC_ASSOCIATION_COPYOBJC_ASSOCIATION_COPY:关联对象会被释放
  1. 扩展NSString类的方法为例,扩展属性、实例方法和类方法,使用runtime实现属性的gettersetter,代码如下:
//  NSString+Category.h

#import <Foundation/Foundation.h>

@interface NSString (Category) {
    /*不可添加成员变量*/
}
@property(nonatomic,copy) NSString *newString;
//扩展的实例方法和类方法
+(void)categoryClassMethod;
-(void)categoryInstanceMethod;
@end
//  NSString+Category.m

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

@implementation NSString (Category)

//runtime强行实现newString的getter和setter
-(NSString *)newString {
    return objc_getAssociatedObject(self, @"newString");
}

-(void)setNewString:(NSString *)newString {
    objc_setAssociatedObject(self, @"newString", newString, OBJC_ASSOCIATION_COPY);
}

//扩展的实例方法和类方法
+(void)categoryClassMethod {
    NSLog(@"这是扩展的类方法");
}
-(void)categoryInstanceMethod {
    NSLog(@"这是扩展的实例方法");
}
@end
  • 在主函数中调用
//  main.m

#import <Foundation/Foundation.h>
#import "NSString+Category.h"

int main(int argc, const char * argv[]) {
    NSString *string = [[NSString alloc] init];
    
    //runtime实现的getter和setter
    string.newString = @"你好";
    NSLog(@"%@",string.newString);
    
    //扩展的类方法和实例方法
    [NSString categoryClassMethod];
    [string categoryInstanceMethod];
    
    return 0;
}
  • 运行结果如下

在这里插入图片描述

2. Extension

2.1 位置

  • 在类的.m文件中@implementation之前的地方,即类的continuous区域

2.2 为啥要用

  • 类扩展的作用本来是私有方法的前向声明,但最新的编译器可以在.m文件中任意位置写实现而无需声明,如果声明了就一定要实现
  • 现在Extension区域的作用主要是定义类的私有属性,将暴露给外部的属性、变量和方法定义在.h文件中,不想暴露的直接定义在.m文件的Extension
  • 私有并不是绝对的,仍然可以使用KVCruntime暴力访问私有属性和变量、使用runtime暴力访问私有方法

2.2 关于添加变量

  • Extension是编译器决议的,它就是类的一部分,因此可以添加成员变量
  • Category运行期决议,不能添加成员变量
/*类扩展区域*/
@interface extensionClass()

/* 类扩展属性,类外部不可访问*/
@property(nonatomic, copy) NSString* extensionVariable;

/* 类扩展方法声明,可省略,若声明了就得在后面实现 */
-(void)extensionInstanceMethod;
+(void)extensionClassMethod;

标签:Category,Extension,方法,void,扩展,NSString,newString
来源: https://blog.csdn.net/qq_35087425/article/details/113768623

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有