上篇文章對iOS下的撥打電話方式進(jìn)行了比較详炬,發(fā)現(xiàn)當(dāng)使用一種方式是實(shí)現(xiàn)不了又兼容所有版本,又能在撥打電話后得知是否撥打了電話的需求時(shí),筆者的想法就是將他們綜合在一起來實(shí)現(xiàn)這個(gè)需求,下面就來講講如何做贰锁。
先上代碼地址:demo地址
demo中使用一個(gè)NSString+MakeCall 分類里的WZ_makeCall方法進(jìn)行撥打電話。
-(void)WZ_makeCall:(WZ_MakeCallBlock )block;
你只需要一兩行代碼變可以實(shí)現(xiàn):撥打電話前彈出提示框沛简,提示用戶是否撥打電話秽晚,并且在用戶點(diǎn)擊呼叫按鈕后會得到一個(gè)成功的回調(diào),基本上適用了開發(fā)中所需要適配的iOS系統(tǒng)版本。
使用代碼如下:
//字符串直接調(diào)用
[@"187XXXX3435" WZ_makeCall:^(BOOL success) {
//點(diǎn)擊了呼叫按鈕了修己,回調(diào)會返回成功標(biāo)示恢总,你可以在這里將數(shù)據(jù)統(tǒng)計(jì)到你們的后臺
}];
嗯,看著還不錯(cuò)的樣子睬愤,哈哈片仿。
下面講解下大致的實(shí)現(xiàn)過程:
拿到需求后,一開始是打算使用WebView的方式尤辱,因?yàn)檫@種方式在任何版本下都能彈出提示框砂豌,但是后來發(fā)現(xiàn)無法獲取到用戶是否點(diǎn)擊了呼叫按鈕還是取消按鈕,嘗試過hook掉UIAlertView的方法光督,比如alloc阳距,init等方法來獲取到這次彈框創(chuàng)建,但是都無法hook 到结借,估計(jì)是因?yàn)槭窍到y(tǒng)彈出的吧筐摘,代碼環(huán)境不在一起。
所以無法hook到映跟,就只能另外找路了蓄拣。
后來發(fā)現(xiàn),在彈出提示框的點(diǎn)擊呼叫按鈕后努隙,系統(tǒng)總是會調(diào)用AppDelegate的以下方法球恤,具體流程見下圖:
在點(diǎn)擊呼叫按鈕后(點(diǎn)擊取消按鈕不會調(diào)用)系統(tǒng)會依次調(diào)用圖中步驟1,2,3 然后再撥出電話,通話結(jié)束后就返回App荸镊,然后再步驟4咽斧。圖中步驟1標(biāo)紅是因?yàn)樵谙到y(tǒng)彈出AlertView時(shí)如果我們等待一段長的時(shí)間后再點(diǎn)擊呼叫按鈕,而不是立馬點(diǎn)擊呼叫按鈕躬存,這時(shí)只會走步驟2张惹,步驟3然后再步驟4不走步驟1.
所以在這里可以假性認(rèn)為,如果在我們調(diào)用了WebView呼叫方式后,彈出了提示框并且系統(tǒng)依次走了2岭洲,3步驟則是開始了通話宛逗。所以無法得知是否點(diǎn)擊了呼叫按鈕的問題解決了。
獲取到2盾剩,3步驟執(zhí)行了的方式雷激,就是注冊系統(tǒng)的兩個(gè)通知name:UIApplicationWillResignActiveNotification和UIApplicationDidBecomeActiveNotification,然后在接收通知調(diào)用的方法里記錄調(diào)用痕跡就可以了告私,代碼如下:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
通知調(diào)用方法:
-(void)applicationWillResignActive{
if (self.didBecomeActive) {
if (self.makeCallBlock) {
//移除通知以及webView屎暇,執(zhí)行回調(diào)
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
self.makeCallBlock(YES);
self.cacheWebV= nil;
self.makeCallBlock = nil;
}
}
}
-(void)applicationDidBecomeActive{
//調(diào)用該方法后,再調(diào)用applicationWillResignActive就是開始通話了驻粟,這里記錄調(diào)用了該方法
self.didBecomeActive = YES;
}
但是WebView方式還有一個(gè)問題根悼,就是撥打電話的時(shí)候比較卡頓,在使用的時(shí)候總是要幾秒后才出現(xiàn)提示框,這在用戶體驗(yàn)上是很差勁的挤巡,在能不用他的情況下最好不用剩彬。剛好在iOS9.0后open URL:方式撥打電話會返回到自身App內(nèi)了,這時(shí)我們只要自己彈出一個(gè)提示框就可以替代WebView方式了玄柏,而且這種方式能知道是否撥打了電話(方法返回Yes就是撥打了)襟衰。
在iOS9上找到替代WebView撥打方式的解決方法,但到了iOS10.2后發(fā)現(xiàn)問題又來了粪摘,open URL:方法自己會彈出提示框了,如果我們還自己彈出提示框就會出現(xiàn)兩次绍坝,所以這里就判斷了一下系統(tǒng)版本在進(jìn)行彈框徘意。后面再優(yōu)化了下,因?yàn)閕OS10后openUrl方法出現(xiàn)了替代方法openURL:options:completionHandler:轩褐。所以這里在iOS10后就不用openUrl方法了椎咧。
總結(jié):
筆者也還在學(xué)習(xí)當(dāng)中,這里只是給出一種解決方式把介,也許代碼中有些不足勤讽,還請大家勿怪,多多幫忙指正拗踢。
補(bǔ)充:
其實(shí)對于獲知使用UIWebView方式撥打電話是否撥打了電話脚牍,還有一種方式,實(shí)現(xiàn)CXCallController的callObserver的代理方法:
- (void)callObserver:(CXCallObserver *)callObserver callChanged:(CXCall *)call;
在系統(tǒng)進(jìn)行通話時(shí)巢墅,該方法就會被調(diào)用诸狭。所以在一定時(shí)間內(nèi)這樣也可以假性認(rèn)為點(diǎn)擊了呼叫按鈕。