原因
当一个实现文件.m代码过多时,将代码分散到各个分类的实现文件中,结构清晰,便于调试
分类能够为系统类添加一些方法,当然通过继承也能够达到相同的效果
可以将一些内部使用的私有方法放入私有分类(就是class-continuation分类,也就是类的实现文件.m)中,隐藏实现细节
实现
下面是实现个人信息的例子,如代码描述,个人信息有Friendship、Work、Paly三个分类,接口文件进行简单的划分,并在.m文件中实现。
//FSJPerson.h
#import <Foundation/Foundation.h>
@interface FSJPerson:NSObject
@property (nonatomic, copy, readonly) NSString *firstName;
@property (nonatomic, copy, readonly) NSString *lastName;
@property (nonatomic, strong, readonly) NSArray *friends;
-(id)initWithFirstName:(NSString *)firstName andLastName:(NSString *)lastName;
@end
@interface FSJPerson(Friendship)
-(void)addFriend:(FSJPerson*)person;
-(void)removeFriend:(FSJPerson*)person;
-(BOOL)isFriendWith:(FSJPerson*)person;
@end
@interface FSJPerson(Work)
-(void)performDayWork;
-(void)takeVocationFromWork;
@end
@interface FSJPerson(Play)
-(void)goToTheCinema;
-(void)goToSportsGame;
@end
当.m文件中的代码量越来越多时,就可以将代码分散到各个.m文件中,这就是iOS中得Category,实现方法如下:
创建分类文件
FSJPerson+Friendship(.h/.m)
FSJPerson+Work(.h/.m)
FSJPerson+Play(.h/.m)
实现分类文件
//FSJPerson+Friendship.h
#import"FSJPerson.h"
@interface FSJPerson(Friendship)
-(void)addFriend:(FSJPerson*)person;
-(void)removeFriend:(FSJPerson*)person;
-(BOOL)isFriendWith:(FSJPerson*)person;
@end
//FSJPerson+Friendship.m
#import"FSJPerson+Friendship.h"
@implementation FSJPerson(Friendship)
-(void)addFriend:(FSJPerson*)person
{
...
}
-(void)removeFriend:(FSJPerson*)person
{
...
}
-(BOOL)isFriendWith:(FSJPerson*)person
{
...
}
@end
注意
因为分类方法加入类中这一操作是在运行期系统加载分类时完成的,运行期系统会把分类中所实现的每一个方法都加入类的方法列表中,如果类中本来就有此方法,而分类又实现了一次,那么分类中得方法会覆盖原来那一份实现代码
结论:总是为第三方类的分类名称加前缀(包括分类名、分类方法名)分类里也可以声明属性,但是分类无法合成与属性相关的实例变量,所以开发者需要在分类中为该属性实现存取方法。否则会出现如下错误:
解决1:在@implementation中把存取方法声明为@dynamic,告诉编译器这些方法运行时再提供,并且需要在消息转发机制在运行期拦截调用时提供实现。
解决2:通过关联对象方式将属性与特质关联,让系统为之提供方法。
解决3:尽量避免在分类中声明属性