一、应用场景
我们需求是push之后一个界面,再pop回来,需要检测一下,如果不符合,就再Pop回去。(其实这样的动画也不是太好。)
二、正常的敲代码
A push B push C
[self.navigationController popViewControllerAnimated:YES]; // C回来
if (YES) { // 某种检测逻辑(联网检测) B页面
[self.navigationController popViewControllerAnimated:YES]; // 连续pop
}
这时候我们惊人的发现,iOS7的机子crash。这时候内心是抓狂的。顿时觉得,这什么破需求碰上了系统没有优化的bug(iOS8以上(含)系统已自动修复)。
这时候我们解决办法就是等上一个pop结束。再检测pop。上一个pop结束的时机就是B页面viewDidAppear
和C页面的viewDidDisappear
三、黑魔法给pop添加完成回调
给UIViewController
交换方法实现
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self swizzleOriginMethod:@selector(viewDidDisappear:) anotherSelecor:@selector(xks_viewDidDisappear:)];
});
}
- (void)xks_viewDidDisappear:(BOOL)animated {
[super xks_viewDidDisappear:animated];
void(^popCompeletion)() = objc_getAssociatedObject(self, @"popCompeletion");
if (popCompeletion) {
popCompeletion();
}
}
给UINavigationController
给增加分类,pop回调
- (void)popViewControllerAnimated:(BOOL)animated compeletion:(void(^)())compeletion {
UIViewController *topVC = self.topViewController;
__weak typeof(topVC) weakTopVC = topVC;
void(^popCompeletion)() = ^{
__strong typeof(weakTopVC) topVC = weakTopVC;
BOOL directPop = [objc_getAssociatedObject(topVC, @"directPop") boolValue];
if (!directPop) { // 预防compeletion被多次执行
objc_setAssociatedObject(topVC, @"directPop", @(YES), OBJC_ASSOCIATION_ASSIGN);
if (compeletion) {
compeletion();
}
}
};
objc_setAssociatedObject(topVC, @"popCompeletion", popCompeletion, OBJC_ASSOCIATION_COPY_NONATOMIC);
[self popViewControllerAnimated:animated];
}
四、优雅的使用
给目标C植入block
__weak typeof(self) weakSelf = self;
cVC.compeletion = ^{
__strong typeof(weakSelf) self = weakSelf;
// C回来之后,再pop
[self.navigationController popViewControllerAnimated:YES compeletion:{
if (YES) { // 某种检测逻辑(联网检测) B页面
[self.navigationController popViewControllerAnimated:YES]; // 连续pop,pop到A
}
}];
};