The iPhone Wiki is no longer updated. Visit this article on The Apple Wiki for current information. |
CoreUI
Summary
CoreUI is a private system framework used for managing Asset Catalog files with the .car
file extension, usually found in App or Framework bundles with the name Assets.car (ie, /System/Library/PrivateFrameworks/UIKitCore.framework/Assets.car
),
Whenever an app is compiled through Xcode into a .app
, the images in the xcassets (which is where apps store images that they want to keep on-disk) are compiled into a Assets.car file that is then stored in the Application Bundle, though differing by platform, for iOS apps the file is stored in AppName.app/Assets.car
and for macOS apps the file is in AppName.app/Contents/Resources/Assets.car
Whenever an app tries to retrieve an image that it bundled (or from another bundle) using UIImage's +[UIImage imageNamed:]
/ UIImage(named:)
initializer, UIKit opens the app's Assets.car file from the app bundle (or another bundle if one was specified through the bundle:
parameter) through CoreUI's CUICatalog
's class, and tries to find an image asset with the same name as the one specified using the catalog with -[CUICatalog imageWithName:(NSString *)arg0 scaleFactor:(CGFloat)arg1]
Asset Catalog File Format
As mentioned above, image sets and images are stored in the app's compiled Assets.car
file and retrieved using the CoreUI framework (with UIKit's UIImage being the public interface to retrieve images which internally uses CoreUI), internally, .car files are BOM files (see: https://blog.timac.org/2018/1018-reverse-engineering-the-car-file-format/), remnant from the NeXTSTEP era, though unlike normal .bom
files, .car files contain several BOM blocks & trees which are parsed by the CoreUI framework, the BOM blocks of .car files include:
CARHEADER
block: contains information about number of assets, has a fixed size of 436 bytesEXTENDED_METADATA
block: contains information about the authoring tool (the tool compiling the .car), the deploymentPlatform & deploymentPlatformVersion, as well as thinningArguments used when compiling the asset catalog.
Renditions
.car files are made up of objects called renditions, renditions can represent a wide variety of objects, though only images have been mentioned in this page, there are a variety of other objects, including (but possibly not limited to?):
- SVG
- PNG and JPEG image
- Color
- Icon
- Raw data stored as NSData (see: https://developer.apple.com/documentation/foundation/nsdata?language=objc)
- Image Set
- Multisize Image Set, which do not actually include any images but rather just an array of
CGSize
objects representing image sizes
Renditions are represented by the CUIThemeRendition class, which is usually retrieved with catalogs using the -[CUICatalog enumerateNamedLookupsUsingBlock:(void (^)(CUINamedLookup *))block]
, which enumerates over the named lookups in a catalog and takes in a block (a closure, if you're familiar with Swift) that provides a CUINamedLookup, containing a CUIThemeRendition property named _rendition
Idiom
The platform to which a rendition belongs is called it's idiom, a rendition's idiom can be checked with the CUINamedLookup
from which it came from with the idiom
property (-[CUINamedLookup idiom]
), which is just a number that comes from an enum, the values are as follows:
universal
: value = 0, this means that the rendition is suitable for all platformsiPhone
: value = 1iPad
: value = 2AppleTV
: value = 3CarPlay
: value = 4Apple Watch
: value = 5Marketing
: value = 6, this means that the rendition is meant for App Store related stuff
There is also one more, Mac Catalyst, though that's not checked by the idiom property but rather by checking if the named lookup's subtype is equal to 32401.
Appearance
Renditions can optionally be classified as being meant for dark / light / high contrast / high contrast (dark or light) appearances, this means you can have 2 renditions with the same name however with different appearances, and CoreUI will fetch the correct rendition based on the current device appearance (dark or light mode, etc), the constants for them are as follows:
Any
: value = 0, there is no set appearance for the renditionDark
: value = 1, this rendition is to be used when the device uses dark modeLight
: value = 4, this rendition is to be used when the device uses light modeHigh Contrast Dark
: value = 3, this rendition is to be used when High Contrast is on and the device uses dark modeHigh Contrast Light
: value = 5, this rendition is to be used when High Contrast is on and the device uses light mode