Aspects簡介:
? ? Aspects github地址:https://github.com/steipete/Aspects.git
?? Aspect是一個基于metho swizzing的iOS函數(shù)替換的第三方庫秦躯,他可以很好的實現(xiàn)勾取一個類或者一個對象的某個方法忆谓,這個庫對外的兩個重要接口聲明如下:
? 通過這兩個函數(shù)可以很好得對某一個類的所有實例和某一個實例的對應(yīng)方法進行攔截。一個很好的使用場景踱承,公司產(chǎn)品要求倡缠,要對用戶的頁面軌跡進行統(tǒng)計哨免,也即用戶每次進入到一個控制器調(diào)用viewWillAppear函數(shù)時進行相應(yīng)的處理,現(xiàn)在有以下處理方式昙沦。
? ? 1琢唾、在每一個自定義的控制器的viewWillAppear函數(shù)添加處理代碼
? ? 2、自定義一個集成于UIViewController的基類桅滋,在viewWillAppear添加處理代碼慧耍,然后只有所有的需要統(tǒng)計的控制器都繼承自這個基類控制器。
? ? 3丐谋、使用Aspects來勾取UIViewController類的viewWillAppear方法芍碧,在勾取的函數(shù)里添加代碼
其中方式1代碼重復(fù)太多,需要修改的地方較多号俐,不易維護泌豆,方式2由于要所有的類都繼承自自定義基類,需要額外的溝通成本吏饿,不可取踪危,方式三可以使用自定義類并重寫+ load方法來實現(xiàn)功能,所有以前寫的代碼不用修改一行猪落,只需繼承自UIViewController就可實現(xiàn)功能贞远,這種思想有個專業(yè)術(shù)語叫AOP,即面向切片編程笨忌。
? 網(wǎng)絡(luò)上對于Aspects和method swizzing使用的帖子很多蓝仲,基本用法我也無需贅述,在使用這個庫和method swizzing時我都遇到一個問題:如何實現(xiàn)對一個類的類方法(常說的+方法)進行替換官疲?之前我以為使用Aspects無法實現(xiàn)這個功能袱结,因為畢竟接口只是實現(xiàn)了對-方法和某一對象的-方法進行攔截。
? 于是我開始自己封裝了一個基于method swizzing的庫文件途凫,利用運行時的知識來對類的類方法來進行替換垢夹,demo的地址:https://github.com/2446886848/ZHMethodSwizzingDemo.git 實現(xiàn)起來效果還不錯,但是畢竟Aspects是經(jīng)過眾多開發(fā)者考驗的一個方式维费,而且作者考慮的全面性和穩(wěn)定性也必然會高很多果元。于是我開始試著實現(xiàn)使用Aspects,配合少許的代碼來實現(xiàn)對類方法的替換犀盟。
? 思路:無論是類的實例對象也好噪漾,類對象也好,從運行時的角度來說都是對象且蓬,只不過他們在使用的過程中被人們區(qū)別化了罷了。既然類對象也是對象题翰,它的方法存在于metal類(元類)中恶阴,那么對于metal類來說诈胜,類對象也只是單純的對象,只要我像對普通的實例方法那樣來處理類對象冯事,那么實現(xiàn)替換類的方法也是可行的焦匈。
? 廢話不多說,拿代碼說話昵仅!
? 首先導(dǎo)入Aspects框架到工程缓熟,可以使用cocoapod也可用直接拖源代碼的方式導(dǎo)入。
? 因為要使用運行時的東西摔笤,接著導(dǎo)入運行時頭文件#import? <objc/runtime.h>
? 自定義一個類够滑,類名為“Cat”,類中聲明了一個類方法+ (void)classFee;
????? 實現(xiàn)+ (void)classFee
???? {
????? NSLog(@"Cat classFee");
???? }
? 然后開始使用Aspects框架了吕世,代碼如下:
??? Class catMetal = objc_getMetaClass(NSStringFromClass(Cat.class).UTF8String);??
??? [catMetal aspect_hookSelector:@selector(classFee) withOptions:AspectPositionAfter usingBlock:^(idaspectInfo){
?????????? NSLog(@"aspectFee");
???? } error:NULL];
? 接著在函數(shù)里面直接調(diào)用[Cat classFee]運行程序彰触,可在輸出控制臺看到輸出結(jié)果
? 至此,即可實現(xiàn)使用Aspects實現(xiàn)類方法攔截命辖。