IOS 切面統(tǒng)計事件解耦

統(tǒng)計這個事情可以說是個巨無語的系統(tǒng),當(dāng)然不把他獨立出來也就不是什么問題了忍宋,只是一堆牛皮癬似得代碼穿插在項目各個地方,畢竟真正應(yīng)用到一個app里的統(tǒng)計都跟業(yè)務(wù)有著很強(qiáng)的綁定關(guān)系震叮,脫離業(yè)務(wù)的統(tǒng)計數(shù)據(jù)基本沒什么大用诗眨,先吐槽一波再開始正文。凄硼。铅协。。

基礎(chǔ)封裝

先從用第三方的來說摊沉,基本上就只是需要包個殼就ok了狐史,建個manager,初始化sdk一封裝,加幾個常用統(tǒng)計方法基本ok骏全。常見的方法就是傳個event名再加個properties傳擴(kuò)展字典苍柏,用戶登錄狀態(tài)綁定注銷,通用字段增刪改吟温,基本上這就滿足了大部分需求序仙。。鲁豪。

如果是純自己手寫潘悼,上面說的殼放著,剩下的仿照sdk來爬橡,基本功能要實現(xiàn)異步隊列記錄往本地寫數(shù)據(jù)治唤,定期上傳,處理好讀寫關(guān)系是關(guān)鍵糙申,這里不多說不是這篇重點宾添。

ps:有個殼才敢放開手折騰優(yōu)化

切面封裝

切面統(tǒng)計其實可以看我之前的IOS 百行代碼切面日志,整個完成的就是切面的封裝柜裸,看過的基本應(yīng)該了解這套邏輯切面的時候不關(guān)心切面方法的參數(shù)的話會非常好用缕陕。

如果業(yè)務(wù)關(guān)聯(lián)強(qiáng)的情況,雖然也能處理但要針對那些業(yè)務(wù)作出對應(yīng)的邏輯疙挺,導(dǎo)致切面封裝里夾雜很多特殊邏輯,下面的方法內(nèi)部要對originAOP拆分取所有參扛邑,甚至要復(fù)制部分業(yè)務(wù)層邏輯過來最后完成一個統(tǒng)計。

-(void)al_logger:(id)log originAOP:(id)originAOP

所以我個人建議這里就封裝些簡單的少參甚至無參的統(tǒng)計铐然,然后基本上簡單的通用統(tǒng)計和業(yè)務(wù)統(tǒng)計建個類或者plist蔬崩,列一下要切面的類和方法就完成了。

凡事都有特例搀暑,如果本身方法內(nèi)多個參數(shù)完成一次統(tǒng)計就不多沥阳,那我之前的百行系列就已經(jīng)足夠你解耦了。

ps:鄭重聲明AOP 至少我現(xiàn)在還沒發(fā)現(xiàn)IOS里怎么實現(xiàn)切面靜態(tài)方法(類方法)

通用統(tǒng)計

通用統(tǒng)計就是可以脫離業(yè)務(wù)完全抽離的部分自点,這部分其實可以設(shè)計部分業(yè)務(wù)承接桐罕,比如通用點擊事件可以把點擊的UI對象擴(kuò)展出一個字典的屬性值,如此對于通用統(tǒng)計來說只是看看有沒有某個屬性有的話就扔到統(tǒng)計里桂敛,和業(yè)務(wù)層沒有關(guān)聯(lián)冈绊,但后面帶來的好處很大!這個最后說埠啃。

App生命周期統(tǒng)計

應(yīng)用生命周期的統(tǒng)計隨便建個類,監(jiān)聽下面的通知就ok了伟恶,當(dāng)然這個類就不能銷毀了碴开,比較懶得做法直接AOPLogger 類擴(kuò)展一下init里監(jiān)聽,因為我本身的類里連init方法都沒重寫。

UIApplicationDidFinishLaunchingNotification (通知名稱) ---> application:didFinishLaunchingWithOptions:(委托方法):在應(yīng)用程序啟動后直接進(jìn)行應(yīng)用程序級編碼的主要方式潦牛。

UIApplicationWillResignActiveNotification(通知名稱)--->applicationWillResignActive:(委托方法):用戶按下主屏幕按鈕調(diào)用 眶掌,不要在此方法中假設(shè)將進(jìn)入后臺狀態(tài),只是一種臨時變化巴碗,最終將恢復(fù)到活動狀態(tài)

UIApplicationDidBecomActiveNotification(通知名稱) ---->applicationDidBecomeActive:(委托方法):應(yīng)用程序按下主屏幕按鈕后想要將應(yīng)用程序切換到前臺時調(diào)用朴爬,應(yīng)用程序啟動時也會調(diào)用,可以在其中添加一些應(yīng)用程序初始化代碼

UIApplicationDidEnterBackgroundNotification(通知名稱)----->applicationDidEnterBackground:(委托方法):應(yīng)用程序在此方法中釋放所有可在以后重新創(chuàng)建的資源橡淆,保存所有用戶數(shù)據(jù)召噩,關(guān)閉網(wǎng)絡(luò)連接等。如果需要逸爵,也可以在這里請求在后臺運行更長時間具滴。如果在這里花費了太長時間(超過5秒),系統(tǒng)將斷定應(yīng)用程序的行為異常并終止他师倔。

UIApplicationWillEnterForegroundNotification(通知名稱) ---->applicationWillEnterForeground:(委托方法):當(dāng)應(yīng)用程序在applicationDidEnterBackground:花費了太長時間构韵,終止后,應(yīng)該實現(xiàn)此方法來重新創(chuàng)建在applicationDidEnterBackground中銷毀的內(nèi)容趋艘,比如重新加載用戶數(shù)據(jù)疲恢、重新建立網(wǎng)絡(luò)連接等。

UIApplicationWllTerminateNotification(通知名稱) ----> applicationWillTerminate:(委托方法):現(xiàn)在很少使用瓷胧,只有在應(yīng)用程序已進(jìn)入后臺显拳,并且系統(tǒng)出于某種原因決定跳過暫停狀態(tài)并終止應(yīng)用程序時,才會真正調(diào)用它抖单。

點擊事件(不包括手勢)

這里點擊事件切面分為3類

1.UIControl的addTarget觸發(fā)萎攒,UIButton都會走UIApplication里的這方法,但需要忽略一部分矛绘,不然會和第二個部分重疊耍休,而且手勢addTarget不走,不過手勢不走正好可以區(qū)分手勢

-(void)sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event;

2.設(shè)置delegate委托式系統(tǒng)點擊觸發(fā)货矮,這里直接切了UICollectionView羊精,UITableView,UITabBarController囚玫,UITabBar喧锦,UIAlertView,UIActionSheet這幾個setDelegate方法抓督,然后加標(biāo)識判斷切委托方法燃少,用Aspects庫的方法swizzing因為他不允許重復(fù)swizzing算雙保險。

3.UIAlertAction切block屬性的set方法铃在,每次setBlock的時候替換成我自己的block阵具,在我的block內(nèi)執(zhí)行設(shè)置的block碍遍。

下面就是協(xié)議,用pod的話AOPLogger/AOPClick就有了阳液,用的時候類擴(kuò)展一下AOPLogger遵守協(xié)議實現(xiàn)對應(yīng)方法

@protocol AOPLoggerClickProtocol

@optional

- (void)alcp_sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event;

- (void)alcp_customIgnore_sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event;

- (void)alcp_collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath from:(id)sender;

- (void)alcp_tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath from:(id)sender;

- (void)alcp_tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController from:(id)sender;

- (void)alcp_tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item from:(id)sender;

- (void)alcp_alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex from:(id)sender;

- (void)alcp_actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex from:(id)sender;

- (void)alcp_alertControllerAction:(UIAlertAction *)action from:(id)sender;

@end

ps:覆蓋可能不全怕敬,漏了什么歡迎git提pull request

手勢統(tǒng)計

這個是切了UIView的addGestureRecognizer方法,每次添加手勢的時候我多加個自己AOPLogger的taget-action到gestureRecognizer對象上帘皿,這樣手勢統(tǒng)計就搞定了东跪。

如果要用這個統(tǒng)計點擊和長按,判斷一下狀態(tài)是結(jié)束的時候統(tǒng)計gestureRecognizer類型是UITapGestureRecognizer,UILongPressGestureRecognizer就行鹰溜,其實手勢的統(tǒng)計或許都在結(jié)束的時候統(tǒng)計區(qū)分下類型就夠了吧虽填!

@protocol AOPLoggerGestureRecognizerProtocol

@optional

-(void)algrp_handleGesture:(UIGestureRecognizer*)gestureRecognizer;

@end

頁面統(tǒng)計

這個太尋常了,感覺沒什么好說奉狈,使用方法如上卤唉,之所以還提供個pod的AOPLogger/AOPPageView,主要是如果要統(tǒng)計瀏覽時長邏輯,自己方便實現(xiàn)(如顯示的時候runtime隨便塞個date進(jìn)去仁期,消失的時候算一下上報)桑驱,還有我默認(rèn)預(yù)先忽略了部分頁面,省了自己寫。

@protocol AOPLoggerPageViewProtocol

@optional

-(BOOL)alpvp_viewIgnore:(id)sender;

-(void)alpvp_viewDidAppear:(BOOL)animated sender:(id)sender;

-(void)alpvp_viewDidDisappear:(BOOL)animated sender:(id)sender;

@end

業(yè)務(wù)統(tǒng)計

業(yè)務(wù)統(tǒng)計首先放的位置要保證在對應(yīng)業(yè)務(wù)線的目錄里跛蛋,畢竟跟業(yè)務(wù)關(guān)聯(lián)密切熬的,大的業(yè)務(wù)邏輯調(diào)整的時候看一下放業(yè)務(wù)統(tǒng)計目錄下對應(yīng)的地方需不需要修改。

無參數(shù)方法統(tǒng)計

這一類就是需要寫在業(yè)務(wù)層里但統(tǒng)計的時候只記錄一個Event名赊级,比如有個方法-(void)abc:(id)a b:(id)b c:(id)c;我只是記錄他被調(diào)用押框,這種直接AOPLogger調(diào)用下[AOPLogger AOPLoggerWithClassString:classString methodString:@"abc:b:c" log:@"abc"]或扔plist里默認(rèn)直接解決。

方法內(nèi)邏輯處理統(tǒng)計

這個就有點厲害了理逊,比如下訂單的時候我買了一堆東西里面帶著各種商品屬性橡伞,要你把某種屬性的商品做統(tǒng)計,只是舉例...這時候直接寫這個類的類擴(kuò)展load方法里切面然后寫邏輯處理統(tǒng)計晋被,這里不建議用Aspects庫兑徘,底層保證切一個類的一個方法一次是好用的,可業(yè)務(wù)層各種奇葩邏輯都會有羡洛,想解耦經(jīng)常用奇招所以最好允許多次切面挂脑,dispatch_once保證自己的邏輯需要的切一次就可以了,可以用我簡單封裝的方法欲侮。

@interface NSObject (AOPLogger)

+(void)al_hookOrAddWithOriginSeletor:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector error:(NSError**)error;

@end

前后邏輯關(guān)聯(lián)統(tǒng)計

這個可以結(jié)合點擊來講崭闲,比上面還要讓人頭疼,類似統(tǒng)計我查看一個東西威蕉,要記錄我在哪點擊的查看以及當(dāng)前頁面的數(shù)據(jù)屬性刁俭,還有從哪來到當(dāng)前頁面的,要查看東西的id韧涨。這個時候就需要結(jié)合通用統(tǒng)計來搞了牍戚,我們在最底層可以做的是把本身點擊的UI對象的默認(rèn)字典屬性和最上層頁面的默認(rèn)字典屬性以及點擊對象target上層UI對象的默認(rèn)字典屬性做統(tǒng)計沙兰,最上層的激活頁面這個是可以在任何地方搞出來的,回頭我可以把類擴(kuò)展放上來翘魄,在任何頁面都可以拿到當(dāng)前頁面,前一個頁面以及頁面屬于第幾層舀奶。底層在響應(yīng)默認(rèn)點擊事件之前處理我們的統(tǒng)計邏輯暑竟,接下來就是怎么把屬性賦值,這個時候就需要我們?nèi)デ忻娈?dāng)前頁面里做model賦值的方法然后同時把想要統(tǒng)計的屬性賦值到當(dāng)前頁面的默認(rèn)字典屬性里育勺,如果這是cell上的button那么賦值cell的時候就可以切面但荤。

總的來說就是尋找UI對象賦值點,然后切面為UI對象添加統(tǒng)計屬性涧至,我們runtime加到所有UI對象上隱藏的默認(rèn)字典屬性字段專門承接關(guān)聯(lián)信息腹躁,底層只做讀取整合,業(yè)務(wù)層切面賦值南蓬。

這個時候就會發(fā)現(xiàn)數(shù)據(jù)對象與UI對象綁定協(xié)議的制定會直接決定實現(xiàn)的復(fù)雜度纺非。

后序

業(yè)務(wù)層的統(tǒng)計我個人認(rèn)為原則上盡量后端做這個事,畢竟要保證統(tǒng)計數(shù)據(jù)的正確性赘方,其實減少前端統(tǒng)計很重要烧颖,畢竟現(xiàn)在web(pc網(wǎng)頁),wap(手機(jī)網(wǎng)頁)窄陡,小程序炕淮,安卓,ios一牽扯業(yè)務(wù)邏輯統(tǒng)計非常需要統(tǒng)一校準(zhǔn)跳夭,不然數(shù)據(jù)絕對超乎你的想象涂圆。

歸納統(tǒng)計解耦思路

統(tǒng)計放到其他端其實解耦思路也是大致相同。币叹。润歉。下面總結(jié):

1.找底層觸發(fā)的事件點

2.業(yè)務(wù)層找賦值點

3.使用AOP的思路對上面的地方進(jìn)行插入我們的統(tǒng)計邏輯

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市套硼,隨后出現(xiàn)的幾起案子卡辰,更是在濱河造成了極大的恐慌,老刑警劉巖邪意,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件九妈,死亡現(xiàn)場離奇詭異,居然都是意外死亡雾鬼,警方通過查閱死者的電腦和手機(jī)萌朱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來策菜,“玉大人酒贬,你說我怎么就攤上這事〈浠簦” “怎么了锭吨?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長寒匙。 經(jīng)常有香客問我零如,道長,這世上最難降的妖魔是什么锄弱? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任考蕾,我火速辦了婚禮,結(jié)果婚禮上会宪,老公的妹妹穿的比我還像新娘肖卧。我一直安慰自己,他們只是感情好掸鹅,可當(dāng)我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布塞帐。 她就那樣靜靜地躺著,像睡著了一般河劝。 火紅的嫁衣襯著肌膚如雪壁榕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天赎瞎,我揣著相機(jī)與錄音牌里,去河邊找鬼。 笑死务甥,一個胖子當(dāng)著我的面吹牛牡辽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播敞临,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼态辛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了挺尿?” 一聲冷哼從身側(cè)響起奏黑,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎编矾,沒想到半個月后熟史,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡窄俏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年蹂匹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凹蜈。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡限寞,死狀恐怖忍啸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情履植,我是刑警寧澤计雌,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站玫霎,受9級特大地震影響白粉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鼠渺,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望眷细。 院中可真熱鬧拦盹,春花似錦、人聲如沸溪椎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽校读。三九已至沼侣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間歉秫,已是汗流浹背蛾洛。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留雁芙,地道東北人轧膘。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像兔甘,于是被迫代替她去往敵國和親谎碍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 統(tǒng)計這個事情可以說是個巨無語的系統(tǒng)洞焙,當(dāng)然不把他獨立出來也就不是什么問題了蟆淀,只是一堆牛皮癬似得代碼穿插在項目各個地方...
    heroims閱讀 1,794評論 1 52
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)澡匪,斷路器熔任,智...
    卡卡羅2017閱讀 134,652評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法仙蛉,內(nèi)部類的語法笋敞,繼承相關(guān)的語法,異常的語法荠瘪,線程的語...
    子非魚_t_閱讀 31,623評論 18 399
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉夯巷,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,709評論 0 9
  • 一年一個中秋趁餐,對于獨自身處異鄉(xiāng)的游子喷兼,有太多原因?qū)е聼o法與家人舉杯團(tuán)圓。關(guān)于中秋后雷,又有太多美好的記憶季惯。 今年中秋,...
    topanga閱讀 452評論 0 1