写点什么

iOS 中的 Category

作者:NewBoy
  • 2022 年 7 月 12 日
  • 本文字数:3204 字

    阅读完需:约 11 分钟

iOS 中的 Category

什么是 Category

  • 在 OC 中,扩展一个类的方式有两种

  • 继承

  • 分类

  • 可以在不修改原来类的基础上,为这个类扩充一些方法

  • 一个庞大的类可以分模块开发



Category 的格式

  • 通过 Category 给某类添加方法,分为声明和实现俩部分

  • 创建 Category 时,必须给 Category 的名称加上专用前缀

  • 创建 Category 的方法时,必须给方法名称加上专用前缀

  • 分类声明


    @interface Person (Play)    - (void)pGotoTheCinema;    - (void)pGotoSportGame;    @end
复制代码


  • 分类实现


    #import "Person+Play.h"    @implementation Person (Play)    - (void)pGotoTheCinema{    }    - (void)pGotoSportGame{    }    @end
复制代码



Category 的类型

  • Class-continuation 类型的 Category

  • 它必须定义在其所接续的那个类的实现文件中

  • 此分类可以声明属性,且此分类没有特定的是现实文件,其中方法都定义在主实现文件中

  • 一般存放不需要对外公开的属性(例子中的 age)


  #import <Foundation/Foundation.h>  @interface Person : NSObject  @property (nonatomic,copy,readonly) NSString *firstName;  @property (nonatomic,copy,readonly) NSString *lastName;  @property (nonatomic,strong,readonly) NSArray *friends;  - (instancetype)initWithFristName:(NSString *)firstName withLastName:(NSString *)lastName;  @end  --------------------  #import "Person.h"  @interface Person()  @property (nonatomic,assign) NSInteger age;  @property (nonatomic,strong,readwrite) NSArray *friends;  @end  @implementation Person  - (instancetype)initWithFristName:(NSString *)firstName withLastName:(NSString *)lastName{      self = [super init];      if (self) {          _firstName = firstName;          _lastName = lastName;      }      return self;  }  @end
复制代码


  • 如果某属性在主接口中声明为“只读”,而类内部要用 setter 方法修改此属性,那么就在 Class-continuation 分类中将其扩展为 “readwrite”(例子中的 friends)


  #import <Foundation/Foundation.h>  @interface Person : NSObject  @property (nonatomic,copy,readonly) NSString *firstName;  @property (nonatomic,copy,readonly) NSString *lastName;  @property (nonatomic,strong,readonly) NSArray *friends;
- (instancetype)initWithFristName:(NSString *)firstName withLastName:(NSString *)lastName; @end
------------------------------- #import "Person.h" @interface Person() @property (nonatomic,strong,readwrite) NSArray *friends; @end
@implementation Person - (instancetype)initWithFristName:(NSString *)firstName withLastName:(NSString *)lastName{ self = [super init]; if (self) { _firstName = firstName; _lastName = lastName; } return self; } @end
复制代码


  • 若想使类遵循的协议不为人知道,则可以在 Class-continuation 分类中声明


  #import <Foundation/Foundation.h>  @class User;  @interface APP : NSObject  @property (nonatomic,strong) User *user;  @end
----------------------------- #import "APP.h" #import "User.h" @interface APP()<UserDelegate>
@end @implementation APP -(void)doSomething{ NSLog(@"dosomething"); } @end
复制代码


  • 普通类型的 Category


    #import "Person.h"    @interface Person (Play)    - (void)pGotoTheCinema;    - (void)pGotoSportGame;    @end    --------------    #import "Person+Play.h"    @implementation Person (Play)    - (void)pGotoTheCinema{    }    - (void)pGotoSportGame{    }    @end
复制代码



Category 的运用

  • 在开发中,类的实现文件特别大,难于管理与维护,因此经常使用分类机制把类的实现代码划分成易于管理的小块,以便单独检视


    #import <Foundation/Foundation.h>    @interface Person : NSObject    @property (nonatomic,copy) NSString *firstName;    @property (nonatomic,copy) NSString *lastName;    @property (nonatomic,strong) NSArray *friendArray;
- (instancetype)initWithFristName:(NSString *)firstName withLastName:(NSString *)lastName; - (void)addPerson:(Person *)person; - (void)removePerson:(Person *)person; - (BOOL)isFriendWithPerson:(Person *)person; - (void)performDayWork; - (void)takeVacationFromWork; - (void)gotoTheCinema; - (void)gotoSportGame; @end
复制代码


  • 实现文件里,所有的方法都写在一个类,内容太多,所以我们可根据其不同功能分成多个分类


    #import <Foundation/Foundation.h>    @interface Person : NSObject    @property (nonatomic,copy) NSString *firstName;    @property (nonatomic,copy) NSString *lastName;    @property (nonatomic,strong) NSArray *friends;    - (instancetype)initWithFristName:(NSString *)firstName withLastName:(NSString *)lastName;    @end    -------------------------    #import "Person.h"    @interface Person (Work)    - (void)wPerformDayWork;    - (void)wTakeVacationFromWork;    @end    -------------------------    #import "Person.h"    @interface Person (Play)    - (void)pGotoTheCinema;    - (void)pGotoSportGame;    @end    -------------------------    #import "Person.h"    @interface Person (Friendship)    - (void)fAddPerson:(Person *)person;    - (void)fRemovePerson:(Person *)person;    - (BOOL)fIsFriendWithPerson:(Person *)person;    @end
复制代码



Category 的注意事项

  • Category 只能添加方法,不能添加属性。因为 Category 中的 @property,只会生成 setter/getter 的方法声明,不会生成实现及私有的成员变量 (在.m 文件(Class-continuation)中的分类可以声明属性,同时也可以生成 setter、getter 方法)


  #import "Person.h"  @interface Person (Play)  @property (nonatomic,copy) NSString *playGameName;  - (void)pGotoTheCinema;  - (void)pGotoSportGame;  @end  -------------  - (void)viewDidLoad {    [super viewDidLoad];    Person *p = [[Person alloc]initWithFristName:@"firstName" withLastName:@"lastName"];    p.playGameName = @"football";}
复制代码


Xcode 会有警告



运行程序会崩溃



  • 如果分类中有和原类中同名的方法,程序只会调用分类里的方法,如果多个分类中都有和原类中同名的方法,程序只会由编译器决定,编译器最后一个执行的方法来响应调用优先级(Category->本类->父类)


#import <Foundation/Foundation.h>@interface Person : NSObject@property (nonatomic,copy,readonly) NSString *firstName;@property (nonatomic,copy,readonly) NSString *lastName;@property (nonatomic,strong,readonly) NSArray *friends;- (instancetype)initWithFristName:(NSString *)firstName withLastName:(NSString *)lastName;- (void)run;@end------------------------------------#import "Person.h"@interface Person (Play)@property (nonatomic,copy) NSString *playGameName;- (void)pGotoTheCinema;- (void)pGotoSportGame;- (void)run;@end-------------------------------------#import "Person.h"@interface Person (Work)- (void)wPerformDayWork;- (void)wTakeVacationFromWork;- (void)run;@end-------------------------------------Person *p = [[Person alloc]initWithFristName:@"firstName" withLastName:@"lastName"];[p run];
复制代码


log:



发布于: 刚刚阅读数: 3
用户头像

NewBoy

关注

虽不年少,艳阳高照 2019.04.10 加入

还未添加个人简介

评论

发布
暂无评论
iOS 中的 Category_ios_NewBoy_InfoQ写作社区