一、类扩展
格式:
@interface 类名()
//属性
//方法
@end
说明:
1、类扩展可以为某一个类添加额外的属性,成员变量,方法等,并且都是该类的私有项
2、类扩展一般都是在.m文件中,在类实现的上方,比如在我们新建UIController时,系统已经为我们写好了类扩展,再其他文件中,如UIView里,我们也可以手写上述格式来使用类扩展
3、通过新建类扩展文件来使用类扩展,但是子类是不能使用父类类扩展成员,因为是父类私有的
二、分类/类别
格式:
@interface 类名(分类名字)
/*方法声明*/
@end
@implementation类名(分类名字)
/*方法实现*/
@end
说明:
1、类别用来为已有的类(通常是系统的类)添加新方法
2、类别一般只扩充方法,不能新增属性和成员变量
三、分类/类别的应用场景
a、扩展系统类方法
这是我们经常使用分类的情形,分类的好处就是在不新建类的情况下,可以通过扩展系统类方法来实现某种功能,例如分类NSString,将日期转换为字符串类型
.h 文件
/**
日期转成字符串
@param date 日期
@param format 格式
@return 日期字符串
*/
+(NSString*)dateToString:(NSDate*)date format:(NSString *)format;
.m 文件
+(NSString*)dateToString:(NSDate*)date format:(NSString *)format{
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:format];
NSString *dateString = [dateFormat stringFromDate:date];
return dateString;
}
这样我们就可以直接通过NSString类来调用日期转字符串方法了:
分类来新增方法b、方法工厂
有时候,我们手写初始化代码时,要写控件的很多样式,通过分类,我们可以快速完成控件初始化。这种方式依旧是新增方法,我们通过给UIButton新增方法来说明:
/**
* 普通的按钮样式
*/
+(UIButton*)buttonNormalWithTitle:(NSString*)title
target:(id)target
selector:(SEL)selector
frame:(CGRect)frame
bgImage:(UIImage*)bgImage
imagePressed:(UIImage*)imagePressed
textColor:(UIColor*)aColor
textFont:(UIFont*)textFont;
这样,我们就可以在初始化时,调用该法类快速完成一个按钮的初始化了,是不是很方便呢?
c、新增属性
一般来说,分类里是不能添加属性的,即使新增里属性,也不会自动生成setter和getter方法,但是OC的特点之一就是动态运行时,我们可以根据这一特性来关联实现setter和getter方法,以达到新增属性的功能
这里我们给UIViewController新增属性为例:
1)、新建UIViewController的分类
新建分类2)、新增属性
@interface UIViewController (Based)
@property (copy ,nonatomic) NSString *name;
@end
3)、使用运行时完成setter和getter方法
#import <objc/runtime.h>
@implementation UIViewController (Based)
-(void)setName:(NSString *)name{
objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
-(NSString *)name{
return objc_getAssociatedObject(self, _cmd);
}
@end
4)、导入文件,使用
self.name = @"LOLITA";
NSLog(@"%@",self.name);
5)、运行结果
运行结果
这里,可能有人会问了,我可以直接在Controller里新增这个属性啊?使用分类做会不会多次一举呢?当然不是,有没有遇到过这样的情况呢?在维护别人的代码时,想针对共用的属性、方法、控件等做统一的管理,但是项目中又没有使用继承,新建一个基础类成本又太大,那么使用分类是你比较好的选择
为何是使用UIViewController来举例呢?笔者在维护别人的代码时,就遇到的上述头疼的问题,就采用来分类来优化项目,将通用部分统统放到了分类中去,并使用懒加载的方式,到了需要的时候才会申请空间,并大大减少了代码量,提高了复用性。
共用的部分通常包括:指示器Loading控件,导航栏视图、自定义返回手势、检查更新、获取网络状态、权限提示框、请求类等等,将这些放到分类中,大大减少了重复造轮子的问题,并且不像继承那样具有依赖性
补充:新增控件
@property (strong, nonatomic) NavigationView *navigationBar;
-(NavigationView *)navigationBar{
NavigationView *navBar = objc_getAssociatedObject(self, _cmd);
if (navBar==nil) {
navBar = [[NavigationView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 64)];
objc_setAssociatedObject(self, @selector(navigationBar), navBar, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
navBar.backgroundColor = RiseColor;
navBar.delegate = self;
[self.view addSubview:navBar];
}
return navBar;
}
-(void)setNavigationBar:(NavigationView *)navigationBar{
objc_setAssociatedObject(self, @selector(navigationBar), navigationBar, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
四、体会
1、合理的使用分类可以很好的简化代码
2、如果有不正确的地方,或者有其他分类的使用,欢迎留言交流
3、针对笔者的问题,如果有更好的解决办法,也欢迎留言交流,谢谢
网友评论