There is a rumor that something called UXKit exists as part of the Apple Photos application, enabling the same codebase to run on macOS and iOS. Though the article is probably incorrect in that this is an UIKit implementation for macOS:
UIKit for macOS already exists, and it is called UXKit I heard about UXKit when Apple first introduced the new Photos app for macOS.
At ZeeZide we are using something along the lines to build all applications for both, macOS and iOS. One demo of that are the CodeCows and ASCII Cows applications, which share about 90% of the code, while offering unique system features on both platforms (e.g. Stickers on iOS and System Services on macOS).
This is not only useful for actual deployment to macOS, but also during development, as it saves you a lot of the simulator or device testing hassle if you develop for macOS first. (e.g. you can do CoreBluetooth development on macOS)
The Apple acquired UXKit is not an official API, and there are good reasons for this. UXKit is more of a hack to get stuff running in both environments, and not a beautiful framework wrapping UIKit and/or AppKit.
This codebase while not small, has very little 'actual' code. Most stuff is just typealiases, constant aliases, etc.
The idea of this is NOT to provide a full cross platform abstraction.
It is expected that a lot of apps will still carry
#if os(macOS) like code to
enable/disable specific features.
WORK IN PROGRESS: Still cleaning up the stuff.
How to do write Cross-Platform Code using UXKit
Generally instead of using
NSView, you are using
UXKit. UXKit provides a lot of such aliases to streamline the available classes.
Sometimes different aliases point to the same class in one or the other
framework. For example UIKit has
UITextField as distinct
classes, while AppKit uses
NSTextField for both, readonly and editable
In UXKit you should then use the more specific UXKit variant. E.g. on AppKit,
UXLabel for readonly texts and
UXTextField for editable lines, even
though both alias to
NSTextField. This way the code will work right on
Note: The far majority of those are really just typealiases and not subclasses.
- all views have
- uses accessibilityIdentifier on UIKit (is that OK?)
- special type in Swift 4
In UIKit one can attach multiple handlers to a single control action,
and quite often there are multiple options on when the action fires
This isn't usually available in AppKit. In AppKit a control usually has
a single target, and usually one action (sometimes a second for double clicks).
When doing a UXKit application, the code needs to constraint itself to using a single, 'semantic', action. For example this UIKit code:
button.addTarget(self, action: #selector(doIt(:_)), for: .touchUpInside)
And works on both, UIKit and AppKit.
- gestures (below)
UITableView is incorrectly labeled 'table view' - it really is a
'list view' with support for sections.
NSTableView is an actual tableview with support for columns
(and also sections).
There are other differences. For example UIKit has a
is a full implementation of a cell which can be used as-is in the table view.
On AppKit, the corresponding
NSTableCellView is just a shallow wrapper object
maintaining just outlets to associated labels and such.
To streamline the porting, UXKit adds a
NSTableViewCell which matches the
All of those are properly aliases to the corresponding UX names (i.e.
Another example is that UIKit requires the datasource to return an instance
UITableViewCell or a subclass of it.
In AppKit you can return arbitrary views. So avoid doing that when you write
Row editing is also different on UIKit and AppKit. For example reordering is done using drag&drop on AppKit, while UIKit has special builtin support for that.
- sectioned list view vs table view vs outline view
- source lists
- integrate the
- VC vs View factory
- items are VCs on AppKit and Views on UIKit
- layouts can be shared
Layer based views
- explain the tricky parts
- e.g. how layers transforms are reset in unexpected ways on AppKit
- representedObject for UIKit
- formatters attached to controls
UXKit is brought to you by ZeeZide. We like feedback, GitHub stars, cool contract work, presumably any form of praise you can think of.