?????? 前段時間公司開始禁止使用第三方sdk秽褒,這對于程序猿的我來說無疑是一次毀滅性的打擊斜做,開發(fā)時間變得無可估量了柄错,其中分配到我名下的任務(wù)就是要仿造友盟數(shù)據(jù)統(tǒng)計收集這個功能埃碱,這個東西說難不難嚎尤,說簡單不簡單荔仁,數(shù)據(jù)統(tǒng)計肯定要求數(shù)據(jù)的準(zhǔn)確性,首先要完成的是統(tǒng)計頁面使用這個模塊芽死。今天這里就說說統(tǒng)計頁面使用這個模塊的思路乏梁,同時附上代碼,由于開發(fā)時間緊迫关贵,代碼的封裝性簡潔性不那么強遇骑,重在理解思路,沒有思路就不可能實現(xiàn)業(yè)務(wù)邏輯揖曾。
? ? ??? 首先要搞明白一點落萎,數(shù)據(jù)收集的目的說白了就是更加深入了解用戶習(xí)慣和用戶行為亥啦,通過分析這些數(shù)據(jù)能更好的理解用戶意圖,從而改進提高產(chǎn)品的質(zhì)量练链。大數(shù)據(jù)的時代翔脱,沒有統(tǒng)計數(shù)據(jù)這塊的產(chǎn)品肯定會落伍。
???????? 下面直接正題不廢話媒鼓,進入頁面使用統(tǒng)計這個模塊正題届吁。
???????? 需求:用戶每進入一個頁面就需要對該次操作進行記錄,包括頁面(ViewController)的title, 上一個頁面(LastViewController)的title,進入該頁面的時間等等字段需要記錄绿鸣。
? ? ? ? 思路:首先要進行準(zhǔn)確的統(tǒng)計疚沐,必須要先了解控制器(ViewController)的生命周期,生命周期有按照以下順序進行調(diào)用:
當(dāng)一個視圖控制器被創(chuàng)建枚驻,并在屏幕上顯示的時候濒旦。 代碼的執(zhí)行順序
1、 alloc ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 創(chuàng)建對象再登,分配空間
2尔邓、init (initWithNibName) 初始化對象,初始化數(shù)據(jù)
3锉矢、loadView ? ? ? ? ? ? ? ? ? ? ? ? ?從nib載入視圖 梯嗽,通常這一步不需要去干涉。除非你沒有使用xib文件創(chuàng)建視圖
4沽损、viewDidLoad ? ? ? ? ? ? ? ? ? 載入完成灯节,可以進行自定義數(shù)據(jù)以及動態(tài)創(chuàng)建其他控件
5、viewWillAppear ? ? ? ? ? ? ?視圖將出現(xiàn)在屏幕之前绵估,馬上這個視圖就會被展現(xiàn)在屏幕上了
6炎疆、viewDidAppear ? ? ? ? ? ? ? 視圖已在屏幕上渲染完成
當(dāng)一個視圖被移除屏幕并且銷毀的時候的執(zhí)行順序,這個順序差不多和上面的相反
1国裳、viewWillDisappear ? ? ? ? ? ?視圖將被從屏幕上移除之前執(zhí)行
2形入、viewDidDisappear ? ? ? ? ? ? 視圖已經(jīng)被從屏幕上移除,用戶看不到這個視圖了
3缝左、dealloc ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 視圖被銷毀亿遂,此處需要對你在init和viewDidLoad中創(chuàng)建的對象進行釋放
那么問題就來了,我們需要對頁面進行準(zhǔn)確的統(tǒng)計渺杉,那么我們記錄控制器被使用的方法必須寫在唯一的系統(tǒng)API里面蛇数,那么首先就可以把viewWillAppear、viewWillDisappear 排除在外是越,明顯這兩個方法不符合我們的需求耳舅,因為控制器無論調(diào)用viewDidLoad 還是從上級頁面調(diào)popViewControllerAnimated 這個方法,當(dāng)前頁面都會調(diào)用viewWillAppear這個函數(shù)倚评,這就會導(dǎo)致我們統(tǒng)計頁面的數(shù)據(jù)不準(zhǔn)確挽放。那么再回到上面幾個方法里看绍赛,alloc init更不可能,這些方法只是讓控制器在系統(tǒng)中分配內(nèi)存并初始化辑畦,并不適合寫入我們記錄控制器的操作吗蚌,至于loadview這個方法也不太現(xiàn)實,特別是純代碼構(gòu)建視圖的童鞋纯出,更加要排除在外蚯妇,那么只剩下viewDidLoad、viewDidDisappear暂筝、dealloc這三個方法適合我們?nèi)懭胛覀兿胍涗浛刂破鞅皇褂糜涗浀拇a了箩言,這里我選擇了viewDidLoad、dealloc這兩個方法里做文章焕襟,原因很簡單陨收,這兩個函數(shù)在整個控制器的生命周期百分百的只會被調(diào)用一次,不可能再多鸵赖,那就滿足了我們的需求了务漩。好了,首先我們明確了我們該在哪個系統(tǒng)方法里去做文章了它褪,接下來就是解決怎么做文章的問題了饵骨。
?????? 每個控制器都要統(tǒng)計被使用的次數(shù),那么這里我們要盡可能的去把通用的東西提煉出來茫打,確保效率居触。我們首先統(tǒng)計每個控制器被初始化時候的數(shù)據(jù)(生成這個頁面的數(shù)據(jù)記錄),這里我創(chuàng)建了一個管理類老赤,當(dāng)然是個單例轮洋,代碼如下
PageCollectionManger.h
@interface PageCollectionManger : NSObject
- (void)viewControllerDidLoadByController:(BaseViewController *)currentController andPageName:(NSString*)pageName;
+(instancetype)sharedInstance;
@end
PageCollectionManger.m
@implementation PageCollectionManger {
}
static PageCollectionManger *manger = nil;
+(instancetype)sharedInstance {
return [[self alloc] init];
}
- (instancetype)init {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manger = [super init];
});
return manger;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manger = [super allocWithZone:zone];
});
return manger;
}
- (void)viewControllerDidLoadByController:(BaseViewController *)currentController andPageName:(NSString*)pageName{
NSMutableArray *array = [NSMutableArray arrayWithCapacity:0];
for (UIViewController *controller in currentController.navigationController.viewControllers) {
[array addObject:controller];
}
NSString *str = @"";
UIViewController *vc = [[UIViewController alloc] init];
if (array.count>=2) {
vc = array[array.count-2];
str = vc.title;
}
NSLog(@“l(fā)astPage—%@“,str);
NSLog(@“currentPage—%@“,currentController.title);
}
@end
然后我們只需要在每個控制器的viewDidLoad方法里面調(diào)一句代碼就可以記錄當(dāng)前控制器和上級控制器了,代碼如下:
[[PageCollectionManger sharedInstance] viewControllerDidLoadByController:self andPageName:self.tilte];
注意:這句代碼要在你設(shè)置完控制器的title后調(diào)用L1子琛!嚷狞!
到這里我們的工作只完成了一半块促,我們不能只管生荣堰,不管死床未。
關(guān)于控制器的銷毀怎么去記錄:一般我們在項目里頭, 所有的控制器都會繼承自一個BaseViewController這玩意振坚,那么當(dāng)然我們要在這個父類里去做手腳了薇搁,下面我把我寫的BaseViewController的代碼粘貼出來,這里只需要在delloc方法里去做文章渡八,因為每一個控制器的銷毀意味著返回到上一級的控制器了啃洋,所以對于上一級控制器來說传货,當(dāng)前控制器就是LastViewController,而上一級控制器只需要遍歷當(dāng)前所有的控制器取索引為array.count-2即可。
BaseViewController.m
- (void)dealloc{
//pop的邏輯
[self gogogo];
NSLog(@"返回上一個頁面");
}
- (void)gogogo {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:0];
for (UIViewController *controller in self.navigationController.viewControllers) {
[array addObject:controller];
}
NSString *str = @"";
UIViewController *vc = [[UIViewController alloc] init];
if (array.count>=2) {
vc = array[array.count-2];
str = vc.title;
}
NSLog(@"lastPage---%@",self.title);
NSLog(@"currentPage----%@",str);
}
因為每次控制器在調(diào)用popViewControllerAnimated之后就會調(diào)用dealloc,也可以理解為當(dāng)返回上一級頁面時我就把上一級頁面的currentpage和lastpage兩個字段給記錄下來宏娄。
到這里 我們就能完整的保證了每個頁面在用戶的使用中顯示一次記錄一次问裕,保證了準(zhǔn)確性,時間有限孵坚,肯定有不少疏漏之處粮宛,這僅僅是給和我一樣遭遇的童鞋一個思路,如有錯誤請指正卖宠。