UIAppearance tintColor 优先于 Storyboard tintColor

UIAppearance tintColor takes priority over Storyboard tintColor

我使用包含 UIImageView 和 UIButton 的 Interface Builder 创建了一个简单的视图控制器。在它们两个上,我将 tintColor 设置为洋红色。

在 AppDelegate 上,我将 UIView.appearance.tintColor 设置为青色。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    UIView.appearance.tintColor = UIColor.cyanColor;

    return YES;
}

当 运行 我得到这个应用程序时:

这对我来说没有意义。我希望直接在 imageView 和按钮上指定的 Magenta tintColor 覆盖 Cyan tintColor。

为什么会这样?

作为参考,我使用的是 Xcode 版本 11.2 (11B52)。

在您的 ViewController class 中以编程方式设置 tintColor 。

UIImageView也是继承自UIView,改变[=18=的外观]View(UIImageView 的父级)将影响整个应用程序。如果您想覆盖任何特定 UI 元素的外观,请创建一个 IBOutlet 并以编程方式将其更改为仅该 UI 元素。

原来 tintColor 属性 没有用 UI_APPEARANCE_SELECTOR 装饰,所以它不应该在 UIAppearance 代理中使用。

即使看起来有效,设置 UIView.appearance.tintColor 也有副作用。一个例子是故事板的这个问题。我注意到的另一种情况是,在 iOS 13 中,UITableView 部分 headers 将被设置的颜色填充。

鉴于它不是受支持的方案,因此很难准确说明为什么尝试覆盖故事板上的组件 tintColor 不起作用。再次检查文档,我发现了一个可能会解释它的注释:

iOS applies appearance changes when a view enters a window, it doesn’t change the appearance of a view that’s already in a window. To change the appearance of a view that’s currently in a window, remove the view from the view hierarchy and then put it back.

我假设 "storyboard" tintColor 将在加载故事板时设置 object,然后 UIKit 将在视图插入视图后用 "UIAppearance" tintColor 覆盖它层次结构。

解决方法

设置全局 tintColor 的正确方法似乎是在主 UIWindow 上设置它。根据UIView.h中的注释,tintColor被superview继承。这允许对所有视图使用全局 tintColor 并在需要时在本地覆盖它。从故事板设置 属性 时,它按预期工作。