最近在項(xiàng)目中遇到一個(gè)問題, 當(dāng)一個(gè)提示頁面是用present彈出并且?guī)?dòng)畫時(shí),一個(gè)個(gè)分別彈出沒有問題.但是當(dāng)需要同時(shí)彈出頁面并且一個(gè)疊一個(gè)時(shí)就會(huì)導(dǎo)致presentViewController丟失頁面,原因是當(dāng)上一個(gè)頁面彈出還未執(zhí)行完成的時(shí)候,下一個(gè)頁面present就無法真正的彈出.
這邊我寫一下我的解決方案
1.首先創(chuàng)建一個(gè)類繼承UINavigationController,在項(xiàng)目中這個(gè)類是我的window.rootViewController.
#import <UIKit/UIKit.h>
@interface RootNavigationVController : UINavigationController
@property (nonatomic, strong) dispatch_semaphore_t signal;
@end
如以上代碼所示為RootNavigationVController 添加dispatch_semaphore_t 后續(xù)我們使用信號(hào)量的方式來控制presentViewController的彈出.
2. 重寫- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)())completion 方法:
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)())completion {
//初始化信號(hào)量,最高并發(fā)執(zhí)行 1
if (!self.signal) {
self.signal = dispatch_semaphore_create(1);
}
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//當(dāng)present被調(diào)用時(shí), wait -1,此時(shí)信號(hào)量為0,其他執(zhí)行等待
dispatch_semaphore_wait(self.signal, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC));
dispatch_async(dispatch_get_main_queue(), ^{
//判斷是否是modal視圖
if (self.presentedViewController) {
UIViewController *vc = self.presentedViewController;
while (vc.presentedViewController) {
vc = vc.presentedViewController;
}
//取棧頂?shù)膍odal視圖來執(zhí)行
[vc presentViewController:viewControllerToPresent animated:flag completion:^{
dispatch_semaphore_signal(self.signal); //彈窗完成信號(hào)量 +1 允許下一次彈窗任務(wù)執(zhí)行
if (completion) {
completion();
}
}];
} else { //同上
[super presentViewController:viewControllerToPresent animated:flag completion:^{
dispatch_semaphore_signal(self.signal);
if (completion) {
completion();
}
}];
}
});
});
}
這邊主要就是使用信號(hào)量在進(jìn)入presentViewContrller的時(shí)候?qū)€程進(jìn)行阻塞, 在并發(fā)的時(shí)候讓下一個(gè)執(zhí)行等待.然后completion 的block里面彈窗完成,將信號(hào)量+1,允許下一個(gè)頁面執(zhí)行.同時(shí)判斷上一個(gè)頁面類型使用不同方法進(jìn)行彈窗. 這邊我dispatch_semaphore_wait 的timeout設(shè)置是5秒,不同業(yè)務(wù)根據(jù)需求設(shè)置即可.
3.在業(yè)務(wù)中使用時(shí):
[self.navigationController presentViewController:vc animated:YES completion:nil];
這樣不會(huì)影響原有其他地方的presentViewController方法,使用上也沒有其他變化.