There is a very very dirty solution but it works. We are going to use UIAppearance for this purpose.
First of all we need to prepare a special private extension for UIView to be able to change it's subviews background color.
fileprivate extension UIView {
private struct AssociatedKey {
static var subviewsBackgroundColor = "subviewsBackgroundColor"
}
@objc dynamic var subviewsBackgroundColor: UIColor? {
get {
return objc_getAssociatedObject(self, &AssociatedKey.subviewsBackgroundColor) as? UIColor
}
set {
objc_setAssociatedObject(self,
&AssociatedKey.subviewsBackgroundColor,
newValue,
.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
subviews.forEach { $0.backgroundColor = newValue }
}
}
}
Each time we set subiewsBackgroundColor value UIView will iterate it's subviews and set a new background color for each.
As you can see in the answer below there is a special UIView called _UIAlertControlleriOSActionSheetCancelBackgroundView in UIAlertController's hierarchy which contains a subview with white color (for the cancel button)
Let's try to get it's appearance and use our property to change it's subview color. I guess it's kind of a private api.
if let cancelBackgroundViewType = NSClassFromString("_UIAlertControlleriOSActionSheetCancelBackgroundView") as? UIView.Type {
cancelBackgroundViewType.appearance().subviewsBackgroundColor = .red
}
Place this code in the AppDelegate's didFinishLaunching or a dedicated class.
That's it. Now you can see the cancel button on a red background. Tested on iOS 11.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…