Changes to the AppBackend protocol
Note: See the relevant PR for more info.
There was recently a massive refactoring of the equally massive AppBackend protocol. Here's a
comprehensive-ish list of changes:
AppBackend protocol has been split up into three dozen or so smaller protocols, all
organized within a BackendFeatures namespace enum.
BackendFeatures/Core contains the bare minimum needed for a SCUI app to launch without
crashing immediately. (This one's a true protocol, not a typealias.)BaseAppBackend extends Core with most UI controls, containers, and noninteractive views.
This is the protocol that the App/Backend associated type requires.FullAppBackend contains everything the original protocol had, including all of Base as
well as URL handling, revealing files, the global menu, file dialogs, alerts, sheets, corner
radii, web views, tables, gestures, menus, paths, colors, tooltips, date pickers, and some
windowing functionality.
BackendFeatures/RevealFiles, the canRevealFiles property has been removed in favor
of simply not conforming to the protocol if revealing files isn't supported.Code in the SwiftCrossUI target has been updated to use BaseAppBackend instead of just
AppBackend. Backend instances are dynamically casted to additional protocols as needed.
A new internal macro, CastBackend, was added to simplify the task of casting backends. It has
the following signature:
@attached(body)
internal macro CastBackend<NewBackend>(
backendGenericName: String? = nil,
returnsWidget: Bool = false
)
It currently only works correctly within implementations of View methods, but since that's
where most of the boilerplate resides, this macro should still be a huge help.
The backends themselves have been updated for the new organization. Here are the backend protocols each backend conforms to:
BaseAppBackend: all backendsBackendFeatures/Toggles is stubbed for UIKitBackend on all platforms;
BackendFeatures/Sliders is stubbed for UIKitBackend on tvOS.BackendFeatures/ApplicationMenus: all backends except UIKitBackend (except for Mac Catalyst
where it is implemented)BackendFeatures/ExternalURLs: all backendsBackendFeatures/IncomingURLs: all backendsBackendFeatures/RevealFiles: all backends except UIKitBackend and WinUIBackendBackendFeatures/FileOpenDialogs: all backends except UIKitBackend on tvOSBackendFeatures/FileSaveDialogs: all backends except UIKitBackendBackendFeatures/Alerts: all backendsBackendFeatures/Sheets: all backends except WinUIBackend and Gtk3BackendBackendFeatures/CornerRadius: all backends (but janky on Gtk3Backend)BackendFeatures/WebViews: AppKitBackend and UIKitBackend onlyBackendFeatures/Tables: AppKitBackend onlyBackendFeatures/TapGestures: all backendsBackendFeatures/HoverGestures: all backends except UIKitBackend on tvOSBackendFeatures/MenuButtons: all backends except UIKitBackend before iOS 14 / Mac Catalyst 14 / tvOS 17BackendFeatures/Paths: all backendsBackendFeatures/Tooltips: all backendsBackendFeatures/Colors: all backendsBackendFeatures/DatePickers: all backends except Gtk3Backend, and UIKitBackend on tvOSBackendFeatures/WindowClosing: all backends except UIKitBackendBackendFeatures/WindowBehaviors: all backendsA fun side effect of all this that stackotter noticed is that people can now implement missing
backend features in user code — e.g. if someone needs sheets in WinUI, they could simply
declare extension WinUIBackend: BackendFeatures.Sheets in their app.
Of course, we'd want to encourage people to upstream such code into the main project, but this is still a useful thing for people to be able to do. It'd also slightly reduce the (admittedly not large at all) barrier to entry for contributing to SCUI as well as third-party backend projects.