问题:
适配iPad时,调用UIAlertController和UIActivityViewController软件崩溃。iPhone设备上软件运行正常。
错误打印如下:
Thread 1: "UIPopoverPresentationController (<UIPopoverPresentationController: 0x12f33b020>) should have a non-nil sourceView or barButtonItem set before the presentation occurs."
Thread 1: "Your application has presented a UIAlertController (<UIAlertController: 0x103148a00>) of style UIAlertControllerStyleActionSheet from purecolor.RootTabBar (<purecolor.RootTabBar: 0x103810a00>). The modalPresentationStyle of a UIAlertController with this style is UIModalPresentationPopover. You must provide location information for this popover through the alert controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem. If this information is not known when you present the alert controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation."
原因:
UIAlertController和UIActivityViewController这类气泡类视图,在iPad上需要为其指定sourceView和sourceRect,以便让气泡的箭头指向sourceView。
解决:
UIAlertController在类型为actionSheet时会闪退,类型为alert时没影响。
@objc private func longPressViewAction(_ sender: Any) {
guard let topVC = GAScreenUIManager.topViewController() as? LibraryViewController, topVC.className != "UIAlertController" else {
return
}
let alert = UIAlertController(title: nil, message: tempMsg, preferredStyle: .actionSheet)
if UIDevice.current.userInterfaceIdiom == .pad {
var vcPoint = topVC.view.convert(self.center, to: topVC.view)
vcPoint.y = vcPoint.y + UIDevice.navigationBarHeight() - topVC.collectionView.contentOffset.y
alert.popoverPresentationController?.sourceView = topVC.view
alert.popoverPresentationController?.sourceRect = CGRect(x: vcPoint.x, y: vcPoint.y, width: 1, height: 1)
alert.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.any
}
let anyAction = UIAlertAction(title: "复制名称和颜色", style: .default) { action in
}
alert.addAction(anyAction)
let cancelAction = UIAlertAction(title: "取消", style: .cancel) { action in
}
alert.addAction(cancelAction)
topVC.present(alert, animated: true, completion: nil)
}
UIActivityViewController
private func enterActivity(_ img: UIImage) {
let activity = UIActivityViewController(activityItems: [img], applicationActivities: nil)
if UIDevice.current.userInterfaceIdiom == .pad {
activity.popoverPresentationController?.sourceView = self.view
activity.popoverPresentationController?.sourceRect = CGRect(x: UIScreen.main.bounds.size.width - 88, y:0 , width: 88, height: 88)
activity.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.any
}
self.present(activity, animated: true)
}
示意图: