I found a pretty simple workaround and was amazed not to find it anywhere else in the posts. I would like it to be more elegant, but preferable to use the ugly UIImage(named:in:compatibleWith:)
string typifier, in my opinion.
We mainly use the _ExpressibleByImageLiteral
protocol, which is used by Xcode to determine if a type is a literal image literal like this:
struct WrappedBundleImage: _ExpressibleByImageLiteral { let image: UIImage init(imageLiteralResourceName name: String) { let bundle = Bundle(for: ClassInFramework.self) image = UIImage(named: name, in: bundle, compatibleWith: nil)! } }
Note that I'm using a wrapper instead of a subclass of UIImage
, which looks like the best option. Unfortunately, classes like UIImage
are not intended to be a subclass, and you will find that you have a lot of headaches.
And now its use will be:
let image = (🏞 as WrappedBundleImage).image
Not as concise as a regular image literal, but still compilation time is checked :). We just have to remember to cast as
, otherwise our custom initializer will not be called.
You can also do something like this:
extension UIImage { static func fromWrappedBundleImage(_ wrappedImage: WrappedBundleImage) -> UIImage { return wrappedImage.image } }
And now we can use it as follows:
UIImage.fromWrappedBundleImage(🏞)
Hope this helps!
source share