[iOS] XAspect

XAspect 代码注入

  XAspect是一个轻量级的面向切面编程的库。它能允许你在每一个类和每一个实例中存在的方法里面加入任何代码。

使用 CocoaPods 安装

1
pod 'XAspect'

新建文件:XAspect-***.m
文件名规则:(建议)
  XAspect-功能相关.m
举例说明:XAspect-LogAppDelegate.m,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#import "AppDelegate.h"
#import "XAspect.h"

/**
必须要有的宏定义, 而且必须写在最前面
@param AtAspect: 字段固定, 不能修改
@param LZProjectName: 这个可以自定义, 一般和自己需要注入代码的类有关
*/
#define AtAspect LogAppDelegate

/**
需要注入代码的类
@param AtAspectOfClass: 固定字段, 不能修改
@param AppDelegate: 需要注入代码的类
*/
#define AtAspectOfClass AppDelegate
// 开辟空间, 这个参数类名需和上面的类一致
@classPatchField(AppDelegate)

/**
需要添加的方法
@param - 方法类型: - 实例方法; + 类方法
@param BOOL 返回值类型
@param UIApplication 方法实体
@return 返回
*/
AspectPatch(-, BOOL, application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions)
{
//日志初始化
NSLog(@"日志初始化");
return XAMessageForward(application:application didFinishLaunchingWithOptions:launchOptions);
}
@end
#undef AtAspectOfClass
#undef AtAspect

解释:
XAspect-LogAppDelegate.m
往AppDelegate类的application:didFinishLaunchingWithOptions:方法内注入代码
测试打印数据NSLog(@”日志初始化”);

@classPatchField(<#ClassName#>) … @end字段来创建一个类来实现你需要注入的代码
使用宏#define AtAspectOfClass <#ClassName#>类定义需要注入代码的类,类名和@classPatchField(<#ClassName#>)中的参数类名要一致

栗子: XAspect-UIViewController.m,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#define AtAspect ViewController
#define AtAspectOfClass UIViewController
@classPatchField(UIViewController)

@synthesizeNucleusPatch(Default, -, void, viewDidLoad);

AspectPatch(-, void, viewDidLoad){

DDLogInfo(@"[Log]: %@'s view did load.", NSStringFromClass([self class]));

return XAMessageForward(viewDidLoad);
}
#undef AtAspectOfClass
#undef AtAspect

解释:
XAspect-UIViewController.m
XAspect实现方法之前,必须保证源类中存在这个方法.
@synthesizeNucleusPatch(Default, -, void, viewDidLoad);可以检测源类是否存在这个方法,如果不存在,回去尝试调用默认的一个方法,否则会抛出异常。
参数说明(Default, -, void, viewDidLoad)

  • 一: 类型, 有两种
    1.Default : 如果当前类及其父类都没有实现这个方法, XAspect会尝试调用默认的一个返回值为nil/0的方法;
    2.SuperCaller : 如果其父类实现了这个方法, 而当前类没有实现, XAspect会去调用父类的方法;
  • 二: 方法类型 - 实例方法; + 类方法
  • 三: 方法返回值类型
  • 四: 方法实体

如果我们想当某个方法不存的时候去指定一个返回值类型, 可以使用这个方法@tryCustomizeDefaultPatch()
例如:如果源类没有实现-application:didFinishLaunchingWithOptions:方法, 我们希望直接返回YES, 可以这么写:

1
2
3
4
@tryCustomizeDefaultPatch(1, -, BOOL, application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions) {
// 不要在这里实现任何逻辑, 只需要返回一个值;
return YES;
}