精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

iOS 統計打點那些事

移動開發
單來說,就是可以動態的在函數調用的前后插一段代碼。iOS 可以使用 Pete Steinberger 開發的 Aspects 這個庫,大致原理是在 runtime 層,通過 swizzle method 來實現的。 來看一個小 Demo

[[148848]]

統計打點是 App 開發里很重要的一個環節,App 的運行狀態、改版后的效果、用戶的各種行為等都需要打點,市面上也有不少可供選擇的第三方庫。 假設產品有這么個需求:當用戶在詳情頁點擊購買按鈕時,記錄一下事件。我們實現起來大概會是這樣

  1. // DetailViewController.m 
  2.  
  3. - (void)onBuyButtonTapped:(UIButton *)button 
  4. // do some stuff, maybe send a request to server 
  5. [XXXAnalytics event:kSomeEventYouDefined]; 

這個需求就這樣輕松搞定了,但細細想想還是有不少問題的:

頁面上會有其他的 Button,可能每個 Button 都要放上這么一段代碼。

這些統計其實跟具體的業務無關,沒必要跟業務代碼混雜在一起,不優雅。

當改版或者重構時,有可能忘了把相應的打點代碼遷移過去。

所以需要一種更好的方式來做這件事,這就是使用 AOP(Aspect-Oriented-Programming),翻譯過來就是「面向切面編程」

通過預編譯方式和運行期動態代理實現在不修改源代碼的情況下給程序動態統一添加功能的一種技術。

簡單來說,就是可以動態的在函數調用的前后插一段代碼。iOS 可以使用 Pete Steinberger 開發的 Aspects 這個庫,大致原理是在 runtime 層,通過 swizzle method 來實現的。

來看一個小 Demo

  1. [UIViewController aspect_hookSelector:@selector(viewWillAppear:) withOptions:AspectPositionAfter usingBlock:^(idaspectInfo, BOOL animated) { 
  2. NSLog(@"View Controller %@ will appear animated: %tu", aspectInfo.instance, animated); 
  3. } error:NULL]; 

這樣在 UIViewController 的 viewWillAppear: 被調用后,還會再調一下我們定義的 Block,這段日志就會被輸出。而打點正好符合這種場景:正事干完之后,額外干一些跟業務無關的事情。

上面的例子,我們通過 AOP 來做的話,大概就是這樣

  1. // DetailViewController.m 
  2. - (void)onBuyButtonTapped:(UIButton *)button 
  3. // do some stuff, maybe send a request to server 
  4. // no need to call [XXXAnalytics event:] 
  5.  
  6. // AppDelegate.m 
  7. - (void)setupAnalytics 
  8. [DetailViewController aspect_hookSelector:@selector(onBuyButtonTapped:) withOptions:AspectPositionAfter usingBlock:^(idaspectInfo, BOOL animated) { 
  9. [XXXAnalytics event:kSomeEventYouDefined]; 
  10. } error:NULL]; 

這樣統計代碼就從業務代碼中剝離出來了。但是又產生了一個新問題,多個 Button Event,豈不是要寫很多行這樣的代碼,「重復」這樣的事情,作為一個程序員怎么能忍,簡單,造一個方法

  1. - (void)trackEventWithClass:(Class)klass selector:(SEL)selector event:(NSString *)event 
  2. [klass aspect_hookSelector:@selector(selector) withOptions:AspectPositionAfter usingBlock:^(idaspectInfo, BOOL animated) { 
  3. [XXXAnalytics event:event]; 
  4. } error:NULL]; 

使用起來就像這樣

  1. - (void)setupAnalytics 
  2. [self trackEventWithClass:DetailViewController selector:@seletor(onBuyButtonTapped:) event:kSomeEventYouDefined]; 
  3. [self trackEventWithClass:ListViewController selector:@seletor(followButtonTapped:) event:kAnotherEventYouDefined]; 
  4. // ... 

看起來又干凈了些。這時,產品經理又提了個需求:當這個按鈕點擊時,如果已經登錄了,發送 EventA,如果沒有登錄則發送 EventB,也就是說,不再只是 [XXXAnalytics event:] 這么簡單了,還需要加上額外的邏輯,這也難不倒我們,加上一個 block 即可。

  1. - (void)trackEventWithClass:(Class)klass 
  2. selector:(SEL)selector 
  3. eventHandler:(void (^)(idaspectInfo))eventHandler 
  4. [klass aspect_hookSelector:@selector(selector) withOptions:AspectPositionAfter usingBlock:^(idaspectInfo, BOOL animated) { 
  5. if (eventHandler) { 
  6. eventHandler(aspectInfo); 
  7. } error:NULL]; 
  8.  
  9. // 使用 
  10. [self trackEventWithClass:DetailViewController selector:@seletor(onBuyButtonTapped:) eventHandler:^(idaspectInfo){ 
  11. user.loggedIn ? [XXXAnalytics event:EventA] : [XXXAnalytics event:EventB]; 
  12. }]; 

好了,現在只要不是太復雜的打點邏輯(那些需要方法上下文變量的)我們都能應付了,接下來就該等產品來驗收了。產品搬了個凳子坐在身邊,然后點一下 Button,看一下 Console,被幾輪蹂躪后,產品也慢慢地接受了這種驗收方式。后來某一天,忽然發現某一項或某幾項數據有異常,然后找到開發,瞄了一眼:哦,這個方法被重構了。或者新加的方法忘了加統計了。只能等到下個版本再加上了,如果只是一般的統計數據倒還好,跟錢相關的就麻煩了。

那么有沒有一種直觀的驗證方式呢?當然,程序員是***的呀。一個理想的狀況是,產品打開 App 后,開啟某個開關就能看到所有會發送 Event 的按鈕,就像這樣

 

其中數字代表了 EventID。如何實現呢?還記得注冊事件時,我們有傳入 class 和 selector 么,一般我們都會有一個 BaseViewController,那么就可以在 BaseViewController 的 viewDidAppear: 里做點文章了。

  1. // BaseViewController.m 
  2. - (void)viewDidAppear:(BOOL)animated 
  3. [super viewDidAppear:animated]; 
  4. // 獲取已經注冊過的 classes 
  5. NSDictionary *registeredClasses = [OurAnalytics sharedInstance].registeredClasses; 
  6.  
  7. [registeredClasses enumerateKeysAndObjectsUsingBlock:^(NSString *className, NSArray *selectors, BOOL *stop) { 
  8. if ([self isKindOfClass:NSClassFromString(className)]) { 
  9. // 如何根據 selector 找到它的宿主? 
  10. }]; 

所以現在問題就剩下,如何根據 selector 找到對應的 Button,這里要注意,有些 Button 可能要等網絡請求完成才會出現,比如 TableViewCell 里的 Button。

沒有想到太方便的方法,簡單粗暴點就是設置個 Timer 每隔一段時間掃一下 subviews,如果是 button 或 包含 tapGesture 的,就拿它們的 action 對比一下,如果 match 就可以高亮那個 button / view 了。

EventID 也一樣,之前在注冊時也會傳一個 EventID 過來,這里直接顯示出來即可。對于那些傳 eventHandler 的就不行了。

所以理論上是可行的,性能上會稍微有點損耗,尤其是當 subViews 的結構比較復雜時,不過只是內部用來做驗證,所以這也不是什么問題。

看起來效果已經不錯了,有沒有可能讓這套體系再靈活一些?比如可以從后端制定打點規則?客戶端只是讀取一個配置文件,就像這樣

  1. - (void)setupAnalytics 
  2. // analyticsRules 是從配置文件中讀取出來的 
  3. [analyticsRules enumerateObjectsUsingBlock:^(NSDictionary *rules, NSUInteger idx, BOOL *stop) { 
  4. Class klass = NSClassFromString(rules[@"class"]); 
  5. SEL selector = NSSelectorFromString(rules[@"selector"]); 
  6. NSString *eventID = rules[@"eventID"]; 
  7. [self trackEventWithClass:klass seletor:seletor event: eventID]; 
  8. }]; 

那如果在后臺的時候填錯了 Class 或 Selector 怎么辦?還好有 objc_getClassList 和 class_copyMethodList 這兩個運行時方法,有了它們就可以在 App 啟動時掃一遍已注冊的類(過濾掉 UI / NS 開頭的),然后將它們的 seletor 也一并保存下來發送給服務端,當然這種操作只需在適當的時機做一下就可以了,比如集成打包時。

現在,這套體系就比較完整了。當然這只是我的一些構想,并沒有在實踐中嘗試過,所以肯定會踩到各種各樣的坑,不過至少看起來是個可行的方案。

責任編輯:chenqingxiang 來源: Limboy
相關推薦

2017-01-10 13:33:51

iOS編程throttle

2021-07-27 10:52:27

iOS WKWebView容器

2024-02-04 17:03:30

2017-05-15 21:50:54

Linux引號

2011-05-19 16:47:50

軟件測試

2012-05-01 08:06:49

手機

2010-07-26 11:02:19

Perl模式匹配

2020-07-29 08:14:59

云計算云遷移IT

2012-01-02 19:30:22

iPad

2009-07-29 10:36:04

北電收購

2011-07-04 15:30:24

Qt 布局 GridLayout

2011-06-30 14:34:17

QT Tablewidge QTableWidg

2011-09-19 15:40:35

2011-12-02 10:32:23

Java

2021-10-19 21:39:51

Unsafe構造器內存

2020-09-23 09:07:16

特權賬號管理PAM網絡安全

2015-05-28 14:02:09

JavaJava日志性

2011-08-22 16:42:43

SqliteiPad

2014-06-06 16:08:17

初志科技

2012-05-31 09:53:38

IT風云15年
點贊
收藏

51CTO技術棧公眾號

久久青草国产手机看片福利盒子| 激情久久久久久| 欧美老女人在线| 欧美性受黑人性爽| 精品国产99久久久久久宅男i| 中文字幕一区二区三区久久网站| 精品伦理精品一区| 男女午夜激情视频| 美女隐私在线观看| 国产成人8x视频一区二区| 97视频在线观看视频免费视频| 欧美一区二区三区成人精品| av在线不卡精品| 亚洲三级在线播放| 久久综合福利| 国产毛片一区二区三区va在线| 亚洲国产美女| 日韩中文在线中文网三级| 亚洲综合伊人久久| 高潮一区二区| 一区二区三区日韩欧美| 日韩久久久久久久| 国产偷人妻精品一区二区在线| 国产亚洲永久域名| 九九热精品视频国产| 日本乱子伦xxxx| 9l亚洲国产成人精品一区二三 | 精品毛片乱码1区2区3区| 亚欧在线免费观看| 末成年女av片一区二区下载| 亚洲三级电影网站| 亚洲精品人成| 九色视频在线播放| 成人精品国产福利| 亚洲自拍另类欧美丝袜| 国语对白做受69按摩| 亚洲成人原创| 欧美丰满老妇厨房牲生活| 国产亚洲精品熟女国产成人| 鲁大师精品99久久久| 日韩视频免费观看高清完整版 | 日韩av一区在线| 亚洲一区二区三区三州| 欧美极品在线| 欧美亚洲一区二区在线观看| 男人天堂网视频| 国产精选在线| 亚洲福利国产精品| 久久av高潮av| 日韩av毛片| 亚洲精品va在线观看| 亚洲自拍三区| 在线激情小视频| 中文字幕免费不卡在线| 日本午夜精品电影| 韩国三级在线观看久| 久久香蕉国产线看观看99| 久久亚洲高清| 青青久草在线| 26uuu国产电影一区二区| 国产一区二区三区免费不卡| 日本人妻熟妇久久久久久| 成人午夜电影网站| 国产成人免费电影| 视频二区在线观看| 久久综合久久鬼色| 免费看成人av| 国产免费av高清在线| 中文无字幕一区二区三区| 图片区小说区区亚洲五月| 91在线直播| 中文字幕综合网| 色一情一乱一乱一区91| 国产在线xxx| 婷婷一区二区三区| 久久精品香蕉视频| av久久网站| 欧美一区二区久久久| 性生活一级大片| 久久99国产精品久久99大师| 日韩国产高清视频在线| 日本黄色小视频在线观看| 天天色综合色| 欧美风情在线观看| 国产成人免费看| 日韩高清不卡一区二区| 国产一区二区在线免费视频| 精品人妻少妇AV无码专区| 成人精品鲁一区一区二区| 蜜桃av噜噜一区二区三区| www.亚洲免费| 一区二区三区在线观看动漫| 色综合久久久久无码专区| 欧美影视资讯| 欧美一级欧美三级| 日韩网站在线播放| 亚洲色图插插| 奇米4444一区二区三区| 中文字幕日本人妻久久久免费| 国产一区二区导航在线播放| 国产在线精品二区| 99re在线视频| 亚洲高清不卡在线观看| 污污的网站18| 精品国产一区二区三区2021| 亚洲精品久久久久久久久| 国产精品久久久久久成人| 亚洲天堂黄色| 国产成人精品在线观看| 国产激情久久久久久熟女老人av| 久久夜色精品国产噜噜av| 日韩一区不卡| 96av在线| 欧美videossexotv100| 久久婷婷五月综合| 亚洲区欧美区| 91网站免费看| 国产永久免费高清在线观看视频| 亚洲一区二区三区四区的| 中文字幕国产传媒| 亚洲bt欧美bt精品777| 欧美老少做受xxxx高潮| 做爰视频毛片视频| 2014亚洲片线观看视频免费| 国产欧美久久久久| 亚洲人成网站在线在线观看| 亚洲男人天堂2024| 天天操天天射天天爽| 激情综合网天天干| 亚洲春色在线视频| 澳门成人av网| 亚洲第一页自拍| 免费网站看av| 国产在线一区观看| 亚洲午夜精品久久久中文影院av| 欧美精品日日操| 亚洲国产精品电影在线观看| 毛片a片免费观看| 国产精品亚洲第一| 欧美性受xxxx黑人猛交88| 久久天天久久| 在线观看视频亚洲| 狠狠狠狠狠狠狠| 久久蜜桃一区二区| 欧美变态另类刺激| 老牛影视av一区二区在线观看| 久久人人爽人人爽人人片亚洲| 中文字幕二区三区| 日本一区二区三区免费乱视频| 人妻丰满熟妇av无码区app| 欧美日日夜夜| 91超碰caoporn97人人| 欧美 日韩 国产 精品 | 欧美在线观看不卡| 91日韩精品一区| 波多野结衣家庭教师在线| 久久97久久97精品免视看秋霞| 97**国产露脸精品国产| 亚洲欧洲综合在线| 欧美性猛交xxxx偷拍洗澡| 亚洲精品视频大全| 亚洲综合精品| 神马影院午夜我不卡| 国产综合色激情| 久热精品视频在线观看| va婷婷在线免费观看| 亚洲国产综合色| 国产乱了高清露脸对白| 日韩精品一级二级| 在线天堂一区av电影| 欧美日本三级| 91国产视频在线播放| 飘雪影视在线观看免费观看 | 久久久久久久久久久久久久久久久久久久 | 国产一区二区在线播放| 99福利在线| 亚洲激情成人网| 中文人妻av久久人妻18| 亚洲国产精品二十页| 天堂网成人在线| 一本色道久久综合亚洲精品不卡 | 亚洲成a人无码| 亚洲视频播放| 一区二区三区|亚洲午夜| 亚洲综合网站| 欧洲成人在线观看| 色影院视频在线| 精品日韩欧美一区二区| 五月婷婷视频在线| 亚洲欧美在线视频| 国产伦精品一区二区三区精品| 欧美一级一区| 国产av第一区| 妖精视频一区二区三区免费观看| 国产精品自产拍高潮在线观看| gogo在线观看| 亚洲欧洲日产国产网站| 国产美女主播在线观看| 午夜欧美2019年伦理| 战狼4完整免费观看在线播放版| 国产盗摄视频一区二区三区| 日韩在线xxx| 亚洲成人av| 蜜桃av噜噜一区二区三| 欧美在线在线| 国产精品久久久久久av| 蜜桃成人365av| 中文字幕亚洲欧美日韩在线不卡| 亚洲欧美激情另类| 欧美电影影音先锋| 久久国产视频一区| 一区二区三区中文字幕| xxxxx99| 91玉足脚交白嫩脚丫在线播放| 三年中文在线观看免费大全中国| 亚洲综合国产激情另类一区| 国产情侣第一页| 日韩在线视频精品| 欧美日韩三区四区| 成人精品毛片| 91久久久久久久久| 国产福利亚洲| 欧洲美女7788成人免费视频| a天堂资源在线| 欧美乱妇40p| 久久久久久久久免费视频| 国产一区二区三区欧美| 亚洲色图 校园春色| 欧美成人福利视频| 国产日韩欧美一区二区东京热| 在线精品国精品国产尤物884a| 亚洲日本韩国在线| 亚洲高清免费视频| 国产精品自拍视频一区| 亚洲国产你懂的| 国产1区2区3区4区| 亚洲日本电影在线| 久久人妻无码aⅴ毛片a片app| 国产偷v国产偷v亚洲高清| av直播在线观看| 99久久久久久99| 四季av综合网站| 岛国精品在线播放| 亚洲欧美日韩偷拍| 成人免费视频网站在线观看| 亚洲成人福利视频| 国产精品亚洲专一区二区三区 | 亚洲三级电影| 国产自产女人91一区在线观看| 国产精品天堂蜜av在线播放 | 亚洲资源在线播放| 欧美三级在线看| 中文字幕 日韩有码| 欧美日韩在线一区二区| 亚洲一区中文字幕在线| 欧美精品在线一区二区三区| 一级片一区二区三区| 欧美日韩第一区日日骚| 国产同性人妖ts口直男| 精品免费一区二区三区| 免费看国产片在线观看| 日韩精品免费观看| 国产高清视频在线播放| 中国china体内裑精亚洲片| av电影在线观看| 久久精品成人欧美大片古装| 91最新在线视频| 国模精品系列视频| 欧美片第一页| 国产精品亚洲欧美导航| 国产精品色婷婷在线观看 | 国产毛片一区二区三区| 视频一区国产精品| 91精品国产91久久久久久密臀| 99久久久精品视频| 免费中文字幕日韩欧美| 国产一伦一伦一伦| 国产精品一区专区| 三级电影在线看| 国产精品色婷婷| 亚洲综合网在线| 懂色av影视一区二区三区| 日韩国产成人在线| 69成人精品免费视频| 日韩在线观看视频一区二区三区| 亚洲欧美日韩精品久久奇米色影视| 99免在线观看免费视频高清| 欧美激情一区二区三区在线视频观看| 黄色漫画在线免费看| 国产精品视频资源| 97品白浆高清久久久久久| 日韩电影在线播放| 欧美精品国产一区| aⅴ在线免费观看| 国产在线视频不卡二| 精品人妻一区二区三区日产乱码卜| 国产精品久久久久四虎| 国产在线一区视频| 欧美日韩亚洲另类| 人妻va精品va欧美va| 在线国产精品视频| 阿v视频在线| 91精品在线播放| 久久99国产成人小视频| 久久99国产精品一区| 久久久久国内| 国产视频精品视频| 中文字幕一区二区三区视频| 日韩人妻无码一区二区三区99| 欧美美女bb生活片| 欧美偷拍视频| 久久久久久久久久久91| 欧洲美女精品免费观看视频| 欧美日韩亚洲一区二区三区在线观看| 一区二区电影在线观看| 国产又粗又长又大的视频| av不卡免费电影| 国产乱国产乱老熟300| 欧美日韩免费在线视频| 日本又骚又刺激的视频在线观看| 欧美成人午夜激情在线| 久久日本片精品aaaaa国产| 欧洲精品在线一区| 亚洲综合另类| 亚洲の无码国产の无码步美| 一区二区三区四区国产精品| 国产精品伊人久久| 中文字幕亚洲无线码在线一区| 国模冰冰炮一区二区| 国内精品**久久毛片app| 欧美一区不卡| 日韩视频在线观看一区二区三区| 欧美国产精品劲爆| 国产黄色免费视频| 亚洲免费视频网站| 日韩伦理在线一区| 国内精品二区| 亚洲免费网站| 特级西西人体wwwww| 黄色一区二区在线观看| 黄色片网站免费在线观看| 午夜免费久久久久| 97se亚洲| 欧美日韩黄色一级片| 91在线国内视频| 欧美激情黑白配| 日韩精品欧美激情| 免费观看一级欧美片| 久久久水蜜桃| 久久在线精品| 欧美激情视频二区| 欧美日韩不卡在线| 黄色国产网站在线播放| 亚洲aaa激情| 欧美日本不卡高清| 亚洲自拍偷拍精品| 欧美日韩亚洲国产一区| 瑟瑟在线观看| 国产精品成熟老女人| 久久免费精品视频在这里| 8x8x成人免费视频| 亚洲综合图片区| 日本xxxxwww| 国产成+人+综合+亚洲欧洲| 成人aaaa| 国产精品久久久久久9999| 一区二区三区四区不卡视频| 天堂在线观看av| 国产a级全部精品| 91欧美日韩| 国产精品嫩草69影院| 色综合中文字幕国产| 成人高清在线| 91视频免费进入| 亚洲一区二区毛片| 天堂а√在线中文在线鲁大师| 91精品国产综合久久久久久久| 51xtv成人影院| 久久99精品久久久久久久青青日本 | 欧美视频免费播放| 中文在线一区二区| 亚洲AV无码一区二区三区少妇| 国内久久久精品| 欧美一区电影| 动漫av在线免费观看| 一本一道久久a久久精品综合蜜臀| av黄色在线观看| 成人免费在线一区二区三区| 免费亚洲一区| 欧洲美女女同性互添| 亚洲国产成人久久| 美女久久久久久| 欧美爱爱视频免费看| 国产精品夫妻自拍| 欧美视频一二区| 国产精品亚洲网站| 一本一本久久| 777777国产7777777| 亚洲老头老太hd| 免费一区二区三区在线视频|