我的应用程序包含可从任何地方显示的模式UIView。 present
方法的工作原理是将视图作为子视图附加到关键窗口上:
func present(_ completion: ((Bool) -> ())? = { _ in }) {
guard !isPresented else {
return
}
if !isBackgroundReady {
initializeBackground()
}
UIApplication.shared.keyWindow?.addSubview(backgroundView)
UIApplication.shared.keyWindow?.addSubview(self)
UIView.animate(withDuration: 0.3, animations: {
self.backgroundView.alpha = 0.35
self.alpha = 1.0
}, completion: { _ in
self.isPresented = true
completion?(true)
})
}
private func initializeBackground() {
backgroundView.backgroundColor = UIColor.black
backgroundView.alpha = 0.0
backgroundView.frame = CGRect(x: UIScreen.main.bounds.midX, y: UIScreen.main.bounds.midY, width: UIScreen.main.bounds.width * 1.2, height: UIScreen.main.bounds.height * 1.2)
backgroundView.center = CGPoint(x: UIScreen.main.bounds.midX, y: UIScreen.main.bounds.midY)
}
此模式包含一个电子邮件链接,用户可以单击该链接打开一个电子邮件提示(如果长按该链接,则显示电子邮件操作表)。此链接是通过使用NSAttributedString
和UITextView上的.link
属性添加的:
let supportString = NSMutableAttributedString(
string: "general.supportEmail".localized(),
attributes: [
.link: "mailto:\("general.supportEmail".localized())",
]
)
supportTextView.attributedText = supportString
但是,当出现电子邮件提示或操作表时,它显示在模式视图的后面:
是否有可能使提示/操作表以当前呈现模态的方式出现在模态视图上方,或者我需要在某种地方添加某种识别器来检测何时出现这些视图之一并暂时关闭该视图。直到我的应用程序视图重新成为焦点?如果是后来的话,我该怎么做?
不是在窗口中添加模态,而是在navicontroller中添加模态-> topviewcontroller。
链接:https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621849-topviewcontroller。
这可能对您有帮助。
关于为什么的快速答案是,您正在窗口的顶部显示自定义模式视图,该视图将显示在所有内容的顶部,并且您的UIAlertController
将显示在UIViewController
上]展示它(位于您的自定义视图下方)。
一种快速的解决方案是始终将您的自定义视图添加为当前“顶部” UIViewController
上的子视图。您可以使用UIViewController
扩展名-像这样:
extension UIViewController {
static func topViewController(_ viewController: UIViewController? = nil) -> UIViewController? {
let viewController = viewController ?? UIApplication.shared.keyWindow?.rootViewController
if let navigationController = viewController as? UINavigationController, !navigationController.viewControllers.isEmpty {
return self.topViewController(navigationController.viewControllers.last)
} else if let tabBarController = viewController as? UITabBarController,
let selectedController = tabBarController.selectedViewController
{
return self.topViewController(selectedController)
} else if let presentedController = viewController?.presentedViewController {
return self.topViewController(presentedController)
}
return viewController
}
}
此扩展名将处理“顶部”的所有UIViewController
,无论是在UINavigationController
,UITabBarController
中还是仅以模态显示等,都应涵盖所有情况。
之后,您可以调整present
方法以考虑到这一点:
func present(_ completion: ((Bool) -> ())? = { _ in }) {
guard !isPresented else {
return
}
if !isBackgroundReady {
initializeBackground()
}
guard let topViewController = UIViewController.topViewController() else { return }
topViewController.view.addSubview(backgroundView)
topViewController.view.addSubview(self)
UIView.animate(withDuration: 0.3, animations: {
self.backgroundView.alpha = 0.35
self.alpha = 1.0
}, completion: { _ in
self.isPresented = true
completion?(true)
})
}