iOS 8 introduces a UIImageAsset class with a method registerImage:withTraitCollection:
. How do I use this class?
Normally, you won't have to. Instead, you'll use an asset catalog. UIImageAsset, in iOS 8, is simply the mechanism underlying image sets in asset catalogs.
For example, in iOS 8, an asset catalog can distinguish between versions of an image intended for different size class situations, using the Width and Height pop-up menus to specify different size class possibilities. Then, when you use an image from an asset catalog in your interface, the right thing happens automatically. If we're on an iPhone with the app rotated to landscape orientation, and if there's both an Any height and a Compact height alternative in the image set, the Compact height version is used. And these features are live; if the app rotates from landscape to portrait, and there's both an Any height and a Compact height alternative in the image set, the Compact height version is replaced with the Any height version in your interface, automatically.
You'll notice that I didn't mention UIImageAsset. However, UIImageAsset is the underlying mechanism. When an image is extracted from an asset catalog through init(named:)
and the name of its image set, its imageAsset
property is a UIImageAsset. All the images in that image set are available through the UIImageAsset; each image has a trait collection associated with it (its traitCollection
), and you can ask the UIImageAsset for the image appropriate to a particular trait collection by calling imageWithTraitCollection:
. That, in fact, is exactly what the interface is doing for you. An interface object that can display an image is automatically trait collection–aware in iOS 8; it receives the traitCollectionDidChange:
message and responds accordingly.
However, it is also possible to combine images into your own UIImageAsset. In a way, this is like making an asset catalog (or at least an image set) in code! In this example, I'll fetch two images out of the app bundle, and configure them so that one is used when the app is in portrait orientation and the other is used when the app is landscape orientation, automatically:
let tcdisp = UITraitCollection(displayScale: UIScreen.mainScreen().scale)
let tcphone = UITraitCollection(userInterfaceIdiom: .Phone)
let tcreg = UITraitCollection(verticalSizeClass: .Regular)
let tc1 = UITraitCollection(traitsFromCollections: [tcdisp, tcphone, tcreg])
let tccom = UITraitCollection(verticalSizeClass: .Compact)
let tc2 = UITraitCollection(traitsFromCollections: [tcdisp, tcphone, tccom])
let moods = UIImageAsset()
let frowney = UIImage(named:"frowney")
let smiley = UIImage(named:"smiley")
moods.registerImage(frowney, withTraitCollection: tc1)
moods.registerImage(smiley, withTraitCollection: tc2)
After that, if frowney
is placed into the interface — for example, by handing it over to a UIImageView as its image, or by assigning it as a UIButton's image — it automatically alternates with smiley
when the app changes orientation.
The remarkable thing is that this magic works even though there is no persistent reference to frowney
, smiley
, or the UIImageAsset (moods
). The reason is that frowney
and smiley
are cached by the system (because of the call to init(named:)
), and they each maintain a strong reference to the UIImageAsset with which they are registered.
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