iOS實(shí)現(xiàn)多個(gè)彈框按順序依次彈出效果
有時(shí)候會(huì)有這樣的需求:App 運(yùn)行完,加載 RootVC ,此時(shí)需要做一些操作,比如檢查更新,之類(lèi)的。此時(shí)可能會(huì)需要有2個(gè)甚至多個(gè)彈框依次彈出。
本篇將以系統(tǒng)的 UIAlertController 作為示例,當(dāng)然,如果是自定義的,也要看一下這篇文章,如何來(lái)處理多個(gè)彈窗。
首先,如果就按照如下的默認(rèn)寫(xiě)法:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"彈框1" message:@"第一個(gè)彈框" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
UIAlertController *alert2 = [UIAlertController alertControllerWithTitle:@"彈框2" message:@"第二個(gè)彈框" preferredStyle:UIAlertControllerStyleAlert];
[alert2 addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:alert2 animated:YES completion:nil];
}
會(huì)有什么問(wèn)題呢?注意控制臺(tái),肯定會(huì)輸出
Warning: Attempt to present <UIAlertController: 0x7ff4c3078c00> on <SCTestViewController: 0x7ff4c2718c20> which is already presenting <UIAlertController: 0x7ff4c283ae00>
所以說(shuō),第二個(gè)彈框應(yīng)該是看不到的。
另一種情況,如果是自定義的 Alert ,你把它 add 為 window 的子視圖,這么做第二個(gè)彈框會(huì)蓋在第一個(gè)上面。如果你用了毛玻璃背景,效果會(huì)更加明顯??隙ú缓线m了。
所以,正確的解決辦法就是類(lèi)似加鎖的過(guò)程,當(dāng)點(diǎn)擊了第一個(gè)彈框的某個(gè)按鈕之后,再?gòu)棾龅诙€(gè)彈框,以此類(lèi)瑞。
這里,我想到用信號(hào)量去解決,但是信號(hào)量會(huì)阻塞線(xiàn)程,不可以直接在主線(xiàn)程使用。所以我們需要在子線(xiàn)程控制信號(hào)量,在主線(xiàn)程創(chuàng)建和顯示 Alert,直接上代碼。
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//創(chuàng)建一個(gè)隊(duì)列,串行并行都可以,主要為了操作信號(hào)量
dispatch_queue_t queue = dispatch_queue_create("com.se7en.alert", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
//創(chuàng)建一個(gè)初始為0的信號(hào)量
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
//第一個(gè)彈框,UI的創(chuàng)建和顯示,要在主線(xiàn)程
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"彈框1" message:@"第一個(gè)彈框" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
//點(diǎn)擊Alert上的按鈕,我們發(fā)送一次信號(hào)。
dispatch_semaphore_signal(sema);
}]];
[self presentViewController:alert animated:YES completion:nil];
});
//等待信號(hào)觸發(fā),注意,這里是在我們創(chuàng)建的隊(duì)列中等待
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
//上面的等待到信號(hào)觸發(fā)之后,再創(chuàng)建第二個(gè)Alert
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"彈框2" message:@"第二個(gè)彈框" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
dispatch_semaphore_signal(sema);
}]];
[self presentViewController:alert animated:YES completion:nil];
});
//同理,創(chuàng)建第三個(gè)Alert
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"彈框3" message:@"第三個(gè)彈框" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
dispatch_semaphore_signal(sema);
}]];
[self presentViewController:alert animated:YES completion:nil];
});
});
}
如此一來(lái),就實(shí)現(xiàn)了我們的需求。
需要注意的是,這里為什么不用全局并發(fā)隊(duì)列,主要是考慮到信號(hào)量會(huì)阻塞線(xiàn)程,優(yōu)先級(jí)特別高,如果此時(shí)隊(duì)列中還有任務(wù),那么就會(huì)等待信號(hào)觸發(fā)。當(dāng)然也有人故意這么做。對(duì)于 “彈框彈出的時(shí)間,不要做其他任何事情” 這種需求是很合適的。當(dāng)然我們千萬(wàn)不能去阻塞主線(xiàn)程!
我們?cè)诋惒骄€(xiàn)程等待信號(hào),在主線(xiàn)程發(fā)信號(hào),如此就可以實(shí)現(xiàn)兩個(gè)線(xiàn)程同步。其實(shí)信號(hào)量就是一種鎖。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
在uiview 的tableView中點(diǎn)擊cell進(jìn)入跳轉(zhuǎn)到另一個(gè)界面的實(shí)現(xiàn)方法
這篇文章主要介紹了在uiview 的tableView中點(diǎn)擊cell進(jìn)入跳轉(zhuǎn)到另一個(gè)界面的實(shí)現(xiàn)方法,首先重寫(xiě)uiviewcontrol方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-10-10
iOS實(shí)現(xiàn)自動(dòng)循環(huán)播放的banner實(shí)例詳解
輪播視圖通常也叫Banner,90%以上App都會(huì)用到的一個(gè)控件,網(wǎng)上有很多開(kāi)源代碼,下面這篇文章主要給大家介紹了關(guān)于利用iOS如何實(shí)現(xiàn)自動(dòng)循環(huán)播放的banner的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-12-12
iOS開(kāi)發(fā)中使用UIDynamic來(lái)捕捉動(dòng)畫(huà)組件的重力行為
這篇文章主要介紹了iOS開(kāi)發(fā)中使用UIDynamic來(lái)捕捉動(dòng)畫(huà)組件的重力行為的方法,代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2015-12-12
iOS App設(shè)計(jì)模式開(kāi)發(fā)中對(duì)interpreter解釋器模式的運(yùn)用
這篇文章主要介紹了iOS App設(shè)計(jì)模式開(kāi)發(fā)中對(duì)interpreter解釋器模式的運(yùn)用,示例為傳統(tǒng)的Objective-C寫(xiě)成,需要的朋友可以參考下2016-04-04
iOS中UILabel實(shí)現(xiàn)長(zhǎng)按復(fù)制功能實(shí)例代碼
在iOS開(kāi)發(fā)過(guò)程中,有時(shí)候會(huì)用到UILabel展示的內(nèi)容,那么就設(shè)計(jì)到點(diǎn)擊UILabel復(fù)制它上面展示的內(nèi)容的功能,也就是Label長(zhǎng)按復(fù)制功能,下面這篇文章主要給大家介紹了關(guān)于在iOS中UILabel實(shí)現(xiàn)長(zhǎng)按復(fù)制功能的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-10-10
詳解Objective-C中的語(yǔ)法糖@{}究竟是什么
這篇文章主要給大家介紹了關(guān)于Objective-C中語(yǔ)法糖@{}究竟是什么的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04

