I find the behavior of the new iOS 13 UIImage property withTintColor(_:renderingMode:)
incomprehensible. What is it for, and how does it relate to the tint color of the context in which the image appears?
For example:
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)
I said .red
. But it's blue:
Evidently it's blue because it takes its color from the tint color of the surrounding context. But then what's the point of giving the image itself a tint color?
But it gets even weirder. I'll draw my own image and give it a tint color:
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)
I said .red
and it's red:
What accounts for the inconsistency?
Few apps on the iPhone give you ways to change their color scheme aside from Dark Mode in iOS 13 and later, but that doesn't mean you can't give an app a new color theme or filtered look. With the Shortcuts app in iOS 14 and later, it's totally possible, and it'll work in practically any app.
Before iOS 13, apps had the opportunity to implement a dark mode themselves. Now, Apple has a system where apps are encouraged — if not expected — to change their themes based on the system theme. Down the line, we expect the relationship between iOS and third-party apps to be much more harmonious when it comes to Dark Mode.
Without the Shortcuts app, you can still change an app's color theme fairly easily using the Accessibility Shortcut. And you'll have more options to do so.
We can change the color of multicolor symbols by set both renderingMode and foregroundColor. <1> We enable multicolor mode by set .renderingMode (.original). <2> We override the color of the symbol's part by setting .foregroundColor. In this case, we set the stroke of the folder to pink.
withTintColor
is probably intended primarily for use only with symbol images, which are always treated as templates and have no color of their own. However, it is also very nice to be able to treat an ordinary image as a template and give it a color.
Let's say you're drawing into a custom UIView's draw(_:)
method, or drawing in a UIImageView graphics context. There has always been a problem with template views; you have no access here to their template behavior, so there is no way to tint them. withTintColor
solves that problem.
There is no doubt, however, that the behavior of these methods is profoundly weird when you use them in any other way:
As soon as you say withTintColor
, the resulting image is treated as a template image, even if you say .alwaysOriginal
. So your rendering mode is now being ignored!
Moreover, in contexts where there is already a tintColor
, there can now be two competing tint colors: that of the context (the surrounding view or the inherited tintColor
) and that of the image when you say withTintColor
. And if this is a template image — a symbol image, or an .alwaysTemplate
image, or an image in a template context like a button — then the context's tintColor
wins, and the color that you specifically applied by saying withTintColor
is ignored!!
For example, this results in a blue symbol image (because the default image view tintColor
is blue) even though you specifically set the symbol image's tint color to red:
let im = UIImage(systemName:"circle.fill")?.withTintColor(.red)
let iv = UIImageView(image:im)
To get a red symbol image, you have to say this:
let im = UIImage(systemName:"circle.fill")?.withTintColor(.red,
renderingMode: .alwaysOriginal)
So in the first code, the tint color you assign is being ignored (we get blue, not red), but in the second code, the rendering mode you assign is being ignored (it's still a template image, but now it's red as requested). Weird, eh?
(I find it very hard to believe that this is the intended behavior, and I've filed a bug, but so far no response from Apple.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With