Tip:發(fā)現(xiàn)在真機(jī)運(yùn)行中有觸發(fā)handoff功能的案例,只需要在代理方法中適當(dāng)返回NO即可荒辕。
關(guān)于iOS Universal Link 的資料不勝枚舉,關(guān)于基礎(chǔ)配置這里就不再詳述弛针。這里主要分享一下李皇,解決其中一個(gè)坑位的過(guò)程...
之前在配置好通用連接后,覺(jué)得完事大吉掉房。然而過(guò)了一段時(shí)間,產(chǎn)品同事來(lái)找茬咯~~~
話說(shuō)瘾杭,沒(méi)想到通用鏈接也有失效這樣一回事哪亿。萬(wàn)惡的蘋果爸爸~~~
基于這個(gè)問(wèn)題的描述如下:
iOS里面有個(gè)情況,打開APP的后在右上角形如:
xxx.com(面包屑導(dǎo)航)跳轉(zhuǎn)到safari后页徐,會(huì)導(dǎo)致Universal Link 跳轉(zhuǎn)失效银萍。
在認(rèn)識(shí)這個(gè)問(wèn)題的時(shí)候恤左,首先需要考慮的是系統(tǒng)版本因素搀绣。發(fā)現(xiàn)在iOS11上通過(guò)通用鏈接啟動(dòng)APP后戳气,右上角并沒(méi)有發(fā)現(xiàn)面包屑導(dǎo)航。而在iOS10和iOS9 上會(huì)出現(xiàn)此問(wèn)題麻捻,所以問(wèn)題明朗了一點(diǎn)呀袱。
iOS11 下系統(tǒng)機(jī)制有所更改,所以本篇命題不會(huì)成立夜赵。
iOS10 以下,系統(tǒng)機(jī)制還不太成熟摊腋,這也是本篇命題存在的意義嘁傀。
能夠讓產(chǎn)品大大樂(lè)此不疲的一定是,某某某家的APP怎么就沒(méi)問(wèn)題呢类咧。所以我們不服氣的研究了一下某某某家的APP蟹腾。這里以兩個(gè)具有代表性的為例。
eg:在微信中娃殖,跳轉(zhuǎn)APP...
今日頭條: 兩顆星
表現(xiàn):呼起APP后,點(diǎn)擊右上角面包屑導(dǎo)航堕虹。會(huì)發(fā)現(xiàn)界面是向右側(cè)跳轉(zhuǎn)到Safari芬首,這一點(diǎn)很像是使用 openURL 實(shí)現(xiàn)的效果。
網(wǎng)易: 一顆星
表現(xiàn):呼起APP后赦政,點(diǎn)擊右上角面包屑導(dǎo)航。WTF!!! 不可點(diǎn)恢着,這個(gè)解決方案就有點(diǎn)雞賊了。
Universal Link:失效的表現(xiàn)从诲,點(diǎn)擊右上角面包屑導(dǎo)航會(huì)發(fā)現(xiàn)頁(yè)面是向左側(cè)pop到Safari靡羡。
向左走還是向右走,簡(jiǎn)直是人生難題碎罚。
對(duì)比以上的結(jié)論:
問(wèn)題根源纳像,面包屑導(dǎo)航打開的是配置好的通用鏈接。這會(huì)讓系統(tǒng)誤以為竟趾,我們以后都會(huì)使用Safari打開通用鏈接從而導(dǎo)致失效岔帽。所以解決問(wèn)題的思路一定是要在,面包屑導(dǎo)航上做文章了犀勒。
能想到的方案如下:
獲取采用從狀態(tài)欄獲取網(wǎng)絡(luò)狀態(tài)的類似方法,來(lái)獲取面包屑導(dǎo)航的相關(guān)狀態(tài)钦购。從而問(wèn)題的解決可以分化為兩個(gè)方案褂萧。
1.在狀態(tài)欄上,貼一層UIView 覆蓋住面包屑導(dǎo)航导犹。這樣的好處是谎痢,iOS9--iOS11都可以獲得一致的體驗(yàn)。難點(diǎn)是要在KeyWindow的最上層添加节猿,否則容易破相。
2.獲取面包屑導(dǎo)航的觸發(fā)事件纫骑,使用運(yùn)行時(shí)替換事件九孩。主要目的是,為我們手動(dòng)調(diào)用openURL 方法提供便利煤墙,并可以修改跳轉(zhuǎn)鏈接為普通鏈接宪拥。
我這里采用了第二套方案,詳細(xì)過(guò)程如下:
抓取面包屑導(dǎo)航:
UIApplication *application = [UIApplication sharedApplication];
NSArray* arrChilden;
arrChilden = [[[application valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];
//查看subView 這個(gè)是沒(méi)有面包屑導(dǎo)航時(shí)的情況
_subviewCache __NSArrayM * @"4 elements" 0x000060000065f6e0
[0] UIStatusBarServiceItemView * 0x7fa4eac8d310 0x00007fa4eac8d310
[1] UIStatusBarDataNetworkItemView * 0x7fa4ead01ec0 0x00007fa4ead01ec0
[2] UIStatusBarBatteryItemView * 0x7fa4ead1b070 0x00007fa4ead1b070
[3] UIStatusBarTimeItemView * 0x7fa4eae76ad0 0x00007fa4eae76ad0
//查看subView 這個(gè)是有面包屑導(dǎo)航時(shí)的情況
_subviewCache __NSArrayM * @"7 elements" 0x1562a850
[0] UIStatusBarBreadcrumbItemView * 0x16df8ff0
[1] UIStatusBarServiceItemView * 0x16875600
[2] UIStatusBarDataNetworkItemView * 0x16b73cd0
[3] UIStatusBarOpenInSafariItemView * 0x15556580
[4] UIStatusBarBatteryItemView * 0x16b594f0
[5] UIStatusBarBatteryPercentItemView * 0x169e0af0
[6] UIStatusBarTimeItemView * 0x16997bb0
其中 UIStatusBarBreadcrumbItemView 就是面包屑左導(dǎo)航
UIStatusBarOpenInSafariItemView 就是面包屑右導(dǎo)航
接下來(lái)深挖 UIStatusBarOpenInSafariItemView脚作,一下就不詳細(xì)說(shuō)了缔刹。其中有一個(gè)事件是我們所關(guān)心的。
SEL: userDidActivateButton:
至此亿扁,入手點(diǎn)有了著落鸟廓。
Final Result:
AppDelegate中修復(fù)方法如下:
///注意 - (void)applicationDidBecomeActive:(UIApplication*)application 方法中調(diào)用)
- (void)fixUniversalLink{
UIApplication *application = [UIApplication sharedApplication];
NSArray* arrChilden;
//是否是iPhoneX
if ([[application valueForKeyPath:@"statusBar"] isKindOfClass:NSClassFromString(@"UIStatusBar_Modern")]) {
arrChilden = [[[[application valueForKeyPath:@"statusBar"] valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];
} else {
arrChilden = [[[application valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];
}
for (id child in arrChilden) {
if ([child isKindOfClass:NSClassFromString(@"UIStatusBarOpenInSafariItemView")]) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class cls = [child class];
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wundeclared-selector"
//原方法
Method originalM = class_getInstanceMethod(cls, @selector(userDidActivateButton:));
#pragma clang diagnostic pop
//替換方法
Method exchangeM = class_getInstanceMethod([self class], @selector(myDidActivateButton:));
method_exchangeImplementations(originalM, exchangeM);
});
}
}
}
#pragma mark - 通用鏈接修復(fù)
- (void)myDidActivateButton:(UIButton*)btn{
NSLog(@"測(cè)試....");
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"http://www.baidu.com"]];
}