作者:代培
位址:http://daipei.me/posts/problem_in_skstoreproductviewcontroller/
轉載請注明出處
我的部落格搬家了,新部落格位址:daipei.me
前言
最近在使用SKStoreProductViewController時遇到很多坑,上網搜尋時發現關于這個東西的讨論不多,stack overflow上也并沒有找到我需要的答案,經過與其3天的抗争,總算是爬出了這些坑,趕緊寫篇部落格冷靜一下。
正文
首先我們先從SKStoreProductViewController說起,這是一個應用内的應用商店,就是說在應用内部無須跳轉到應用商店就可以預覽并下載下傳應用,和在應用商店内部并無差異,體驗是相當不錯,但是如果沒有找到正确的使用姿勢,那麼會讓你苦不堪言。
簡單使用
先看看這個東西該怎麼使用,廢話不多說,直接上代碼。
- (void)viewDidLoad {
[super viewDidLoad];
//首先執行個體化一個VC
SKStoreProductViewController *storeVC = [[SKStoreProductViewController alloc] init];
//然後設定代理,注意這很重要,不如彈出就沒法dismiss了
storeVC.delegate = self;
//接着彈出VC
[self presentViewController:storeVC animated:YES completion:nil];
//最後加載應用資料
[storeVC2 loadProductWithParameters:@{SKStoreProductParameterITunesItemIdentifier:@()} completionBlock:^(BOOL result, NSError * _Nullable error) {
if (error) {
//handle the error
}
}];
}
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController {
//在代理方法裡dismiss這個VC
[viewController dismissViewControllerAnimated:YES completion:nil];
}
簡單的幾行代碼,就可以實作,但是肯定有人會問為何要彈出VC後再加載資料,那樣不會比較慢嗎?提前加載體驗不是會更好嗎?的确是這樣,我也是為了這個好的體驗,跳進了一個深坑,蘋果總是為我們考慮很多。
預加載
在我做了預加載之後,遇到了兩個問題:
- 在彈出StoreVC時沒有反應,并且應用會卡住幾秒
- 彈出一個連取消都沒有的空白VC
在排除了我自身的bug後我确定這是SKStoreProductViewController的問題,上面的兩個問題都是由于預加載出問題時導緻的。
注意我這裡的用詞:預加載出問題而不是出錯,也就是說加載的completion的block還沒調用時,你還不知道這個時候加載出錯時隻是它内部加載有問題時,這時你present這個VC時就會導緻應用卡頓。
對于彈出一個取消按鈕都沒有的空白VC的問題也是因為加載沒有完成,導緻取消沒有顯示出來,當然這個不是必現的,有時還會遇到一種情況就是開始彈出一個沒有取消按鈕的VC,過一會又加載出來了。
是以如果你一定要做預加載的話,唯一的解決方案就是當收到成功的回掉以後才能彈出這個VC,否則放棄這個VC,重新執行個體化一個StoreVC然後彈出并加載(不要忘記設定代理),因為這樣是一定不會出問題的。
為什麼可以這麼肯定呢?因為如果呢執行個體化一個SKStoreProductViewController,不做任何加載工作此時彈出并不會出任何一個問題,隻是這是一個空白的VC,但是取消按鈕一定是存在的,就是說最多讓别人覺得這網速很慢,加載不出來,而不會覺得這是一個bug。
我想補充的是即使這樣做仍然沒法避免彈出空白的VC(無取消按鈕),是以最好的方案就是不做預加載,從表現來看蘋果肯定是希望我們不做預加載的,至于loadProduct方法該在何時調用,在彈出VC前後調用都可以,記住别過早的調用就好。
不要兩次彈出同一個VC
還有一個很奇怪的現象,就是一個做過加載操作的SKStoreProductViewController,在彈出以後,這個SKStoreProductViewController就被廢棄了,什麼意思呢?就是說你不能再次彈出這個VC,不然也會出現上面的bug,就是一個沒有取消按鈕的VC,即使你在彈出前再次調用此VC的load方法,結果都是一樣,他不會理你的,就是不給你彈兩次,這都是一次性的VC,這顯然是蘋果故意為之,隻是不明白這種設計的背後是出于怎樣的考慮。
總結
總之,對于SKStoreProductViewController來說,記住盡量不要去做預加載,因為在網速不錯的情況下彈出後再加載體驗也很不錯,加載速度是很快的,這時根本不需要做什麼預加載,而對于網速不好的使用者,即使做了預加載也可能加載不出來,也不需要做預加載。是以能不做預加載就盡量别做,這裡的預加載隻會讓你無比抓狂!如果呢一定要做預加載,那麼記住一點很重要那就是:隻有收到成功回掉SKStoreProductViewController才能彈出,否則乖乖的彈出後加載,這樣才能避免一些不可描述的bug。