关于 Aspect
在项目中我们经常会广泛使用继承设计模式,例如统一功能的基类BaseModel、BaseView、BaseService,当不复杂的基类用起来还好,当基类的功能种类繁多的时候,通常会造成基类臃肿难以维护,增加额外的学习成本。

base.png
使用切面编程的初衷是我们需要一个职责清晰的基类
Aspect是一款让人用起来愉快的切面编程库,底层是method Swizzling。它允许您为每个类或每个实例的现有方法添加代码,同时考虑插入点,例如在/之前/之后。“Aspect是稳定的,并在数百个应用中使用”——这是选择Aspect最重要的理由。
使用 Aspect + category代替继承
category秉承“为现有类添加功能”的原则,category极大方便了我们对一些类的扩展,是解耦的首选设计模式。
我们采用category + Aspect 的方式来分割,每个功能都有自己的一个category。以UIViewController为例:
UIViewController + NavigationUIViewController + UserEventUIViewController + LogReport
每个类别都在 +(void)load里面声明一下即可在相应的方法里添加函数
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self aspect_hookSelector:@selector(viewDidLoad) withOptions:AspectPositionBefore usingBlock:^(id<AspectInfo>aspectInfo){
[self viewDidLoad:[aspectInfo instance]];
} error:nil];
[self aspect_hookSelector:@selector(viewWillAppear:) withOptions:AspectPositionBefore usingBlock:^(id<AspectInfo>aspectInfo){
[self viewWillAppear:[aspectInfo instance]];
} error:nil];
[self aspect_hookSelector:@selector(viewWillDisappear:) withOptions:AspectPositionBefore usingBlock:^(id<AspectInfo>aspectInfo){
[self viewDidLoad:[aspectInfo instance]];
} error:nil];
});
}
+ (void)viewDidLoad:(UIViewController *)viewController{
NSLog(@"[%@ viewDidLoad]", [viewController class]);
}
+ (void)viewWillAppear:(UIViewController *)viewController{
NSLog(@"[%@ viewWillAppear]",[viewController class]);
}
+ (void)viewWillDisappear:(UIViewController *)viewController{
NSLog(@"[%@ viewWillDisappear]",[viewController class]);
}
将Aspect注册放在+(void)load中,在main函数之前就会运行,所以不需要import。
Tips:关于category
很多小伙伴没有真正理解category的用法,把很多函数都用category来设计。例如之前我见到一个NSString+Path的类别,实现的功能大概是这些
/// eg: documents/12314
+ (NSString *)userFolder;
/// eg:documents/12314/UserInfo
+ (NSString *)userInfoFolder;
/// eg:documents/12314/broon_12314.sqlite
+ (NSString *)databasePath;
/// eg:documents/12314/UserInfo/broon_userInfo.sqlite
+ (NSString *)userInfoDatabasePath;
/// eg:12314
+ (NSString *)userID;
项目配置类的基本上没用到NSString里的功能,所以类似这种情况下的还是老老实实写个NSObject类或者实体类来代替。
我的组件化系列文章:
《iOS组件化》组件化实践
《iOS组件化》组件的划分
《iOS组件化》创建公共/私有 Pods
《iOS组件化》之 搭建适合业务的URL跳转路由-ALRouter
《iOS组件化》之搭建基于AFNetworking的网络请求框架
