iOS 13 `withTintColor` 不遵守我指定的颜色

mat*_*att 7 uiimage ios swift ios13

我发现新的 iOS 13 UIImage 属性的行为withTintColor(_:renderingMode:)难以理解。它的用途是什么,它与图像出现的上下文的色调有什么关系?

例如:

let im = UIImage(systemName:"circle.fill")?.withTintColor(.red)
let iv = UIImageView(image:im)
iv.frame.origin = CGPoint(x: 100, y: 400)
self.view.addSubview(iv)
Run Code Online (Sandbox Code Playgroud)

我说.red。但它是蓝色的:

在此处输入图片说明

显然它是蓝色的,因为它的颜色来自周围环境的色调。但是,给图像本身赋予淡色有什么意义呢?

但它变得更加奇怪。我将绘制自己的图像并给它着色:

let sz = CGSize(width: 20, height: 20)
let im = UIGraphicsImageRenderer(size:sz).image { ctx in
    ctx.cgContext.fillEllipse(in:CGRect(origin:.zero, size:sz))
}.withTintColor(.red)
let iv = UIImageView(image:im)
iv.frame.origin = CGPoint(x: 100, y: 400)
self.view.addSubview(iv)
Run Code Online (Sandbox Code Playgroud)

我说.red,它是红色的:

在此处输入图片说明

不一致的原因是什么?

mat*_*att 21

withTintColor可能主要仅用于符号图像,它们始终被视为模板并且没有自己的颜色。但是,能够将普通图像视为模板并为其赋予颜色也非常好。

假设您正在绘制自定义 UIView 的draw(_:)方法,或者在 UIImageView 图形上下文中绘制。模板视图一直存在问题;您无法在此处访问它们的模板行为,因此无法为它们着色。withTintColor解决了这个问题。

然而,毫无疑问,当您以任何其他方式使用这些方法时,它们的行为非常奇怪:

  • 只要您说withTintColor,生成的图像就会被视为模板图像,即使您说.alwaysOriginal。所以你的渲染模式现在被忽略了!

  • 此外,在已经有 a 的上下文中tintColor,现在可以有两种相互竞争的色调颜色:上下文(周围视图或继承的tintColor)的颜色和当您说 时的图像的颜色withTintColor。如果这是一个模板图像-一个符号图像,或.alwaysTemplate图像,或像一个按钮模板背景图像-那么上下文的 tintColor胜利,而且颜色你专门应用于说withTintColor被忽略!

例如,tintColor即使您专门将符号图像的色调颜色设置为红色,这也会产生蓝色符号图像(因为默认图像视图是蓝色):

let im = UIImage(systemName:"circle.fill")?.withTintColor(.red)
let iv = UIImageView(image:im)
Run Code Online (Sandbox Code Playgroud)

要获得红色符号图像,您必须这样说:

let im = UIImage(systemName:"circle.fill")?.withTintColor(.red,
    renderingMode: .alwaysOriginal)
Run Code Online (Sandbox Code Playgroud)

所以在第一个代码中,你分配的色调颜色被忽略(我们得到蓝色,而不是红色),但在第二个代码中,你分配的渲染模式被忽略(它仍然是一个模板图像,但现在它按照要求变成了红色)。很奇怪吧?

(我发现很难相信这是预期的行为,我已经提交了一个错误,但到目前为止 Apple 没有回应。)