場景: 要對用戶的頁面的軌跡進行統計。
- 在每一個自定義的控制器的viewWillAppear函數添加處理代碼
- 使用派生
- 使用Aspects來勾取UIViewController類viewWillAppear方法,在勾取的函數添加代碼
先說下使用方式1,重複的代碼太多,不易維護。方式2由於要所有的類都繼承自定義的基類,需要額外的溝通成本,均不可取。
下面我們來看方式3,通過需要勾取的類來調用aspect_hookSelector:withOptions:usingBlock
[UIViewController aspect_hookSelector:@selector(viewWillAppear:)
withOptions:AspectPositionAfter
usingBlock:^(id<AspectInfo> aspectInfo)
{//do something} error:NULL];
直接在usingBlock回調中,調用處理代碼即可。
面向切片編程須知
程序要完成一件事情,一定會有一些步驟,1,2,3,4這樣。這裏分解出來的每一個步驟我們可以認爲是一個
切片
。針對每一個切片的間隙,塞一些代碼進去,在程序正常進行1,2,3,4步的間隙可以跑到你塞進去的代碼,那麼你的寫的這些代碼就是
面向切片編程
。你要想到在每一個步驟中間做你自己的事情,不用AOP也一樣可以達到目的,直接在步驟之間塞代碼就好了。但是事實情況往往很複雜,直接把代碼塞進去,主要問題在於:
塞進去的代碼很有可能是跟原業務無關的代碼,在同一份代碼文件裏面摻雜多種業務,這會帶來業務間的耦合
。爲了降低這種耦合度,我們引用了AOP。
AOP的優勢:
- 減少切面業務的開發量,“一次開發終生使用”,比如日誌
- 減少代碼耦合,方便複用。切面業務的代碼可以獨立出來,方便其他應用使用
- 提高代碼review的質量,比如我可以規定某些類的某些方法才用特定的命名規範,這樣review的時候就可以發現一些問題
AOP的弊端:
- 它破壞了代碼的乾淨整潔。
iOS 如何實現AOP
在iOS開發領域,Objective-C的runtime有提供了一些列的方法,能夠讓我們攔截到某個方法的調用,來實現攔截器的功能,這種手段我們稱爲Method Swizzling。
Aspects
Aspects封裝了runtime,Method Swizzing。提供了兩個api,可以很好的勾取一個類或者一個對象的某個方法。
+ (id<AspectToken>)aspect_hookSelector:(SEL)selector
withOptions:(AspectOptions)options
usingBlock:(id)block
error:(NSError **)error;
- (id<AspectToken>)aspect_hookSelector:(SEL)selector
withOptions:(AspectOptions)options
usingBlock:(id)block
error:(NSError **)error;