UIPrintInteractionController在iPad点击取消触发web lock崩溃问题求助
问题根因
报错核心是WebKit相关API在非主线程被调用,你只在回调内部切了主线程,但忽略了两个核心触发点:
- 打印控制器初始化、弹出、关联webView打印格式化器的整段逻辑本身没有确保在主线程执行
- 如果你用的是旧版
UIWebView控件,它的viewPrintFormatter内部会在打印交互结束(包括取消)时触发WebKit内部回调,部分系统版本下该回调默认不会在主线程执行
修复方案
- 先确保整段打印初始化、弹出逻辑全部放到主线程执行,不要只包裹回调部分:
dispatch_async(dispatch_get_main_queue(), ^{ UIPrintInfo *printInfo = [UIPrintInfo printInfo]; printInfo.outputType = UIPrintInfoOutputGeneral; printInfo.jobName = self.title; UIPrintInteractionController *pc = [UIPrintInteractionController sharedPrintController]; pc.delegate = (id <UIPrintInteractionControllerDelegate>)self; pc.printInfo = printInfo; UIViewPrintFormatter *printFormatter = [self.webView viewPrintFormatter]; printFormatter.startPage = 0; pc.printFormatter = printFormatter; __weak SnaglistPrintViewController *weakSelf = self; UIPrintInteractionCompletionHandler completionHandler = ^(UIPrintInteractionController *printController, BOOL completed, NSError *error) { dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"Handler completed: %d", completed); if (!completed && error) { NSLog(@"FAILED! due to error in domain %@ with error code %u", error.domain, (unsigned int)error.code); } else { [weakSelf back]; } }); }; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { [pc presentFromRect:CGRectZero inView:self.view animated:YES completionHandler:completionHandler]; } });
- 如果是
UIWebView导致的兼容性问题,直接替换为WKWebView,WKWebView的线程安全机制可以避免绝大多数这类WebKit非主线程调用崩溃 - 临时兜底方案:如果暂时无法替换WebView,可以先把webView的内容提前渲染成PDF/静态图片,直接给打印控制器传入渲染好的打印项,不再直接关联webView的printFormatter,彻底切断WebKit回调触发的崩溃路径
验证要点
- 点击取消、打印完成两种场景都要测试,确保不会出现线程异常
- 检查当前页面退出时,打印控制器的delegate是否被自动置空,避免野指针崩溃
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

