最近做一個直播項目的時候遇到顯示禮物后隱藏時的bug界斜。之前的邏輯是禮物在面板停留5秒后隱藏,但是隱藏有一個1秒的動畫眯搭,我的所有移除數(shù)據(jù)的邏輯都是在animation的complete里面窥翩,如果在這1秒中再次連擊禮物會出現(xiàn)數(shù)據(jù)錯誤的情況。為了不改變太多現(xiàn)有的邏輯鳞仙,我使用了dispatch_semaphore來解決這個問題寇蚊。
一、關(guān)于dispatch_semaphore
dispatch_semaphore主要使用下面三個方法來完成對線程的控制
//創(chuàng)建信號量棍好,參數(shù):信號量的初值仗岸,如果小于0則會返回NULL
dispatch_semaphore_create(信號量值)
//信號量值-1,如果信號量的值不大于0允耿,wait方法會阻塞線程
dispatch_semaphore_wait(信號量,等待時間)
//信號量值+1
dispatch_semaphore_signal(信號量)
dispatch_semaphore的其他介紹網(wǎng)上太多了扒怖,也介紹的非常詳細较锡,這里就不再贅述了。比如點擊這里有關(guān)于dispatch_semaphore的介紹
二盗痒、案例
A.m
- (void)doSomeAnimation{
//禮物顯示時長+5s蚂蕴,執(zhí)行某些邏輯
......
......
b.removeBlock=^{
//移除數(shù)據(jù),移除視圖
}
}
B.m
- (void)removeView{
[UIView animateWithDuration:1.0 animations:^{
} completion:^(BOOL finished) {
if(self.removeBlock){
self.removeBlock();
}
}];
}
可以很明顯的看出俯邓,按照現(xiàn)有的邏輯骡楼,在移除動畫執(zhí)行的1秒內(nèi),如果doSomeAnimation方法被調(diào)用稽鞭,當(dāng)移除動畫執(zhí)行完畢后鸟整,禮物的view就會被移除。那么就需要川慌,在移除動畫執(zhí)行時吃嘿,doSomeAnimation這個方法的調(diào)用進入等待隊列。
使用dispatch_semaphore來解決這個問題
A.m
- (void)doSomeAnimation{
//使用wait方法梦重,使信號量-1兑燥,如果當(dāng)前信號量不大于0,會阻塞當(dāng)前縣城
dispatch_semaphore_wait(b.sem, DISPATCH_TIME_FOREVER);
//禮物顯示時長+5s琴拧,執(zhí)行某些邏輯
......
......
b.removeBlock=^{
//動畫執(zhí)行完成降瞳,信號量+1
dispatch_semaphore_signal(b.sem);
//移除數(shù)據(jù),移除視圖
}
//使用signal使信號量+1
dispatch_semaphore_signal(b.sem);
}
B.m
- (void)viewDidLoad{
//創(chuàng)建
self.sem = dispatch_semaphore_create(1);
}
- (void)removeView{
//開始執(zhí)行動畫蚓胸,信號量-1
dispatch_semaphore_wait(self.sem, DISPATCH_TIME_FOREVER);
[UIView animateWithDuration:1.0 animations:^{
} completion:^(BOOL finished) {
if(self.removeBlock){
self.removeBlock();
}
}];
}
梳理一下現(xiàn)在的邏輯挣饥,當(dāng)移除動畫開始執(zhí)行時,信號量-1沛膳,那么doSomeAnimation會被堵塞扔枫,當(dāng)執(zhí)行完畢后,信號量+1锹安,doSomeAnimation恢復(fù)正常執(zhí)行短荐。看上去沒什么毛病叹哭,但是現(xiàn)在還有很大的問題忍宋。
當(dāng)連續(xù)調(diào)用兩次wait,把當(dāng)前縣城阻塞之后风罩,removeBlock也會被阻塞糠排,那么就不能執(zhí)行dispatch_semaphore_signal使信號量+1,當(dāng)前線程就相當(dāng)于進入了死鎖狀態(tài)超升。
提供一下解決思路
解決思路入宦,把doSomeAnimation放在子線程中執(zhí)行哺徊,removeBlock放在主線程執(zhí)行,那么在執(zhí)行wait的時候云石,都在子線程中唉工,即使阻塞也只是子線程被阻塞了,當(dāng)移除動畫完成后汹忠,removeBlock在主線程中調(diào)用不會被阻塞dispatch_semaphore_signal方法就會被正常調(diào)用了淋硝。
相信自己能解決的
具體如何改就自己去操作吧,相信你在解決完這個問題后宽菜,對于dispatch_semaphore和死鎖都會有更深的理解了谣膳!