iOS管理多個(gè)彈窗彈出-信號(hào)量應(yīng)用

問(wèn)題和需求

APP在啟動(dòng)完成后瞳遍,一般會(huì)在首頁(yè)有多個(gè)彈窗,這些彈窗大多都是自定義的,網(wǎng)絡(luò)回來(lái)的時(shí)機(jī)也不一定渗常。因此多個(gè)彈窗如果不做處理就會(huì)一起全部彈出來(lái)壮不,這樣會(huì)比較影響體驗(yàn),如果沒(méi)有好的管理方法凳谦,那么維護(hù)就變得困難忆畅。
先附上效果對(duì)比圖


QQ20190520-121517-HD.gif

這個(gè)效果是通過(guò)信號(hào)量實(shí)現(xiàn)的

信號(hào)量概念
信號(hào)量是用于多線程同步的,跟鎖不一樣的是尸执,信號(hào)量不一定是鎖定某一個(gè)資源家凯,而是流程上的概念,比如:有A,B兩個(gè)線程如失,B線程要等A線程完成某一任務(wù)以后再進(jìn)行自己下面的步驟绊诲,這個(gè)任務(wù) 并不一定是鎖定某一資源,還可以是進(jìn)行一些計(jì)算或者數(shù)據(jù)處理之類(lèi)褪贵。而對(duì)于鎖來(lái)說(shuō)掂之,鎖住的資源無(wú)法被其余的線程訪問(wèn),從而阻塞線程而實(shí)現(xiàn)線程同步脆丁。

實(shí)現(xiàn)
首先創(chuàng)建一個(gè)類(lèi)AlertViewManager世舰,實(shí)現(xiàn)單例,用于管理項(xiàng)目中的所有的彈窗槽卫,可以是自定義的彈窗跟压、原生彈窗、權(quán)限申請(qǐng)的彈窗

代碼建議拉到末尾下載DEMO歼培,粘貼代碼到簡(jiǎn)書(shū)有些空格不見(jiàn)了

AlertViewManager.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedefvoid(^ExecuteBlock)(void);
@interfaceAlertViewManager :NSObject
//重要提醒震蒋!:自定義的彈窗不要添加再[UIApplication sharedApplication].keyWindow上, keyWindow是會(huì)變化的,因?yàn)橄到y(tǒng)的彈窗是創(chuàng)建一個(gè)window躲庄,成為keyWindow查剖,當(dāng)系統(tǒng)彈窗消失的時(shí)候,創(chuàng)建出來(lái)的window也會(huì)銷(xiāo)毀噪窘,但是這時(shí)候獲取的keyWindow有可能就是準(zhǔn)備銷(xiāo)毀這個(gè).這樣的自定義彈窗連同keywindow一起被銷(xiāo)毀笋庄,導(dǎo)致信號(hào)一直是鎖著的狀態(tài),無(wú)法彈出后面的彈窗
//系統(tǒng)彈窗消失瞬間獲取到的keyWindow就是系統(tǒng)彈窗那個(gè)keyWindow倔监,自定義彈窗添加上去會(huì)隨著keywindow銷(xiāo)毀而銷(xiāo)毀
+ (nullable instancetype)shareManager;
/**
 彈窗顯示的代碼寫(xiě)進(jìn)BLOCK塊內(nèi)
 @paramexecuteBlock <#executeBlock description#>
 */
- (void)showWithExecuteBlock:(nonnull ExecuteBlock)executeBlock;
/**
 彈窗顯示完畢調(diào)用
 @paramexecuteBlock 可以為空但是一定要調(diào)用
 */
- (void)dismissWithExecuteBlock:(nullable ExecuteBlock)executeBlock;
@end

AlertViewManager.m

#import "AlertViewManager.h"
//全局信號(hào)量
dispatch_semaphore_t_globalInstancesLockSEM;
//執(zhí)行QUEUE的Name
char*QUEUE_NAME_SEM ="com.alert.queueSEM";
//初始化 -- 借鑒YYWebImage的寫(xiě)法
staticvoid_AlertViewInitGlobalSEM() {
    staticdispatch_once_tonceToken;
    dispatch_once(&onceToken, ^{
        _globalInstancesLockSEM = dispatch_semaphore_create(1);
    });
}

@interface AlertViewManager ()
@end
@implementationAlertViewManager
- (void)showWithExecuteBlock:(ExecuteBlock)executeBlock {
    dispatch_async(dispatch_queue_create(QUEUE_NAME_SEM, DISPATCH_QUEUE_SERIAL), ^{
        dispatch_semaphore_wait(_globalInstancesLockSEM, DISPATCH_TIME_FOREVER);
        dispatch_async(dispatch_get_main_queue(), ^{
            if(executeBlock) {
                executeBlock();
            }
        });
    });
}

- (void)dismissWithExecuteBlock:(ExecuteBlock)executeBlock {
    dispatch_async(dispatch_queue_create(QUEUE_NAME_SEM, DISPATCH_QUEUE_SERIAL), ^{
        dispatch_semaphore_signal(_globalInstancesLockSEM);
        dispatch_async(dispatch_get_main_queue(), ^{
            if(executeBlock) {
                executeBlock();
            }
        });
    });
}

+ (instancetype)shareManager {
    return[[self alloc]init];
}

+ (instancetype)allocWithZone:(struct_NSZone*)zone {
    staticidinstan =nil;
    staticdispatch_once_tonceToken;
    dispatch_once(&onceToken, ^{
        instan = [superallocWithZone:zone];
    });
    returninstan;
}

- (instancetype)init {
    if(self= [superinit]) {
        _AlertViewInitGlobalSEM();
    }
    return self;
}
@end

使用方法

系統(tǒng)原生彈窗調(diào)用如下

[[AlertViewManager shareManager] showWithExecuteBlock:^{
        [[[UIAlertView alloc] initWithTitle:@"" message:@"彈窗1" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil] show];
    }];
- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    [[AlertViewManager shareManager] dismissWithExecuteBlock:^{
    }];
}

重要提醒直砂!:

1.自定義的彈窗不要添加再[UIApplication sharedApplication].keyWindow上, keyWindow是會(huì)變化的,因?yàn)橄到y(tǒng)的彈窗是創(chuàng)建一個(gè)window丐枉,成為keyWindow少漆,當(dāng)系統(tǒng)彈窗消失的時(shí)候像啼,創(chuàng)建出來(lái)的window也會(huì)銷(xiāo)毀辟狈,但是這時(shí)候獲取的keyWindow有可能就是準(zhǔn)備銷(xiāo)毀這個(gè).這樣的自定義彈窗連同keywindow一起被銷(xiāo)毀,導(dǎo)致信號(hào)一直是鎖著的狀態(tài)敦腔,無(wú)法彈出后面的彈窗

2.showWithExecuteBlock和dismissWithExecuteBlock要成對(duì)出現(xiàn)。如果沒(méi)有成對(duì)出現(xiàn)翎卓,信號(hào)量計(jì)數(shù)錯(cuò)誤纵潦,會(huì)同時(shí)彈出多個(gè)彈窗或者不彈出

附上Demo: https://github.com/1498522607/HZSAlertViewManager
有什么問(wèn)題歡迎評(píng)論留言

參考并推薦閱讀優(yōu)秀文章

http://www.reibang.com/p/2f0225b67f6c

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市听绳,隨后出現(xiàn)的幾起案子颂碘,更是在濱河造成了極大的恐慌,老刑警劉巖椅挣,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件头岔,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡鼠证,警方通過(guò)查閱死者的電腦和手機(jī)峡竣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)量九,“玉大人适掰,你說(shuō)我怎么就攤上這事≤校” “怎么了类浪?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)肌似。 經(jīng)常有香客問(wèn)我费就,道長(zhǎng),這世上最難降的妖魔是什么锈嫩? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任受楼,我火速辦了婚禮,結(jié)果婚禮上呼寸,老公的妹妹穿的比我還像新娘艳汽。我一直安慰自己,他們只是感情好对雪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布河狐。 她就那樣靜靜地躺著,像睡著了一般瑟捣。 火紅的嫁衣襯著肌膚如雪馋艺。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,598評(píng)論 1 305
  • 那天迈套,我揣著相機(jī)與錄音捐祠,去河邊找鬼。 笑死桑李,一個(gè)胖子當(dāng)著我的面吹牛踱蛀,可吹牛的內(nèi)容都是我干的窿给。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼率拒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼崩泡!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起猬膨,我...
    開(kāi)封第一講書(shū)人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤角撞,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后勃痴,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體谒所,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年召耘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了百炬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡污它,死狀恐怖剖踊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情衫贬,我是刑警寧澤德澈,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站固惯,受9級(jí)特大地震影響梆造,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜葬毫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一镇辉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贴捡,春花似錦忽肛、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至汛骂,卻和暖如春罕模,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背帘瞭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工淑掌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蝶念。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓抛腕,卻偏偏與公主長(zhǎng)得像诈悍,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子兽埃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類(lèi)型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,103評(píng)論 1 32
  • 時(shí)間是尺子,人們用它感知生命的流逝适袜,用它來(lái)制定各種計(jì)劃柄错,用它來(lái)衡量工作效率...... 古時(shí)候,人們用日晷苦酱,圭表售貌,...
    張大俠丶閱讀 304評(píng)論 3 3
  • 第二話 有些人不必客氣 高貴華麗的歐式餐廳中,一個(gè)清秀俊郎的年輕男子安靜的坐在餐桌前疫萤。白皙的干凈的臉龐上看不...
    殤祁祁閱讀 243評(píng)論 2 3
  • 李開(kāi)復(fù)在1月份上了CBS的60minutes欄目颂跨,一下子把這本書(shū)的英文版帶火了。這本書(shū)的英文名是《AI強(qiáng)國(guó)》扯饶,中文...
    SeanCheney閱讀 4,198評(píng)論 0 9
  • 一個(gè)島國(guó)下面有7個(gè)島恒削,各島人數(shù)不一樣。旅行者已經(jīng)在其中一個(gè)島上尾序,他要去各島游歷钓丰,準(zhǔn)備在人口多的島上游玩的時(shí)間長(zhǎng)一些...
    DataMining234閱讀 674評(píng)論 0 1