Here is a UIAlertController
extension that works on both iPad and iPhone. Cancel button will change from a dark colour to white automatically depending on what blurStyle is selected:
extension UIAlertController {
private struct AssociatedKeys {
static var blurStyleKey = "UIAlertController.blurStyleKey"
}
public var blurStyle: UIBlurEffectStyle {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.blurStyleKey) as? UIBlurEffectStyle ?? .extraLight
} set (style) {
objc_setAssociatedObject(self, &AssociatedKeys.blurStyleKey, style, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
view.setNeedsLayout()
view.layoutIfNeeded()
}
}
public var cancelButtonColor: UIColor? {
return blurStyle == .dark ? UIColor(red: 28.0/255.0, green: 28.0/255.0, blue: 28.0/255.0, alpha: 1.0) : nil
}
private var visualEffectView: UIVisualEffectView? {
if let presentationController = presentationController, presentationController.responds(to: Selector(("popoverView"))), let view = presentationController.value(forKey: "popoverView") as? UIView // We're on an iPad and visual effect view is in a different place.
{
return view.recursiveSubviews.flatMap({$0 as? UIVisualEffectView}).first
}
return view.recursiveSubviews.flatMap({$0 as? UIVisualEffectView}).first
}
private var cancelActionView: UIView? {
return view.recursiveSubviews.flatMap({
$0 as? UILabel}
).first(where: {
$0.text == actions.first(where: { $0.style == .cancel })?.title
})?.superview?.superview
}
public convenience init(title: String?, message: String?, preferredStyle: UIAlertControllerStyle, blurStyle: UIBlurEffectStyle) {
self.init(title: title, message: message, preferredStyle: preferredStyle)
self.blurStyle = blurStyle
}
open override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
visualEffectView?.effect = UIBlurEffect(style: blurStyle)
cancelActionView?.backgroundColor = cancelButtonColor
}
}
The following UIView
extension is also needed:
extension UIView {
var recursiveSubviews: [UIView] {
var subviews = self.subviews.flatMap({$0})
subviews.forEach { subviews.append(contentsOf: $0.recursiveSubviews) }
return subviews
}
}
Example:
let controller = UIAlertController(title: "Dark Alert Controller", message: nil, preferredStyle: .actionSheet, blurStyle: .dark)
// Setup controller actions etc...
present(controller, animated: true, completion: nil)
iPhone:
iPad: