CoreUI

From The iPhone Wiki
Jump to: navigation, search

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:

  1. CARHEADER block: contains information about number of assets, has a fixed size of 436 bytes
  2. EXTENDED_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?):

  1. PDF
  2. SVG
  3. PNG and JPEG image
  4. Color
  5. Icon
  6. Raw data stored as NSData (see: https://developer.apple.com/documentation/foundation/nsdata?language=objc)
  7. Image Set
  8. 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:

  1. universal: value = 0, this means that the rendition is suitable for all platforms
  2. iPhone: value = 1
  3. iPad: value = 2
  4. AppleTV: value = 3
  5. CarPlay: value = 4
  6. Apple Watch: value = 5
  7. Marketing: 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:

  1. Any: value = 0, there is no set appearance for the rendition
  2. Dark: value = 1, this rendition is to be used when the device uses dark mode
  3. Light: value = 4, this rendition is to be used when the device uses light mode
  4. High Contrast Dark: value = 3, this rendition is to be used when High Contrast is on and the device uses dark mode
  5. High Contrast Light: value = 5, this rendition is to be used when High Contrast is on and the device uses light mode