SwiftUI On All Devices
(*) marks APIs that were changed since the video was published
SwiftUI is the shortest path to building great apps on every device
SwiftUI is designed to accomodate many UI paradigms – it can be used with a mouse, touch, digital crown, remote, or assistive technologies
It has great support for any specific platform’s conventions out of the box
It was built with the help of experts from all devices, to make sure that on each platform it feels right at home
Learn once and use anywhere
Common elements that render in an appropriate way on every device
Common layout system that works the same way everywhere
More advanced elements like Picker
There’s no such thing as a “one size fits all app” – if you stick to the common denominator across all devices, you’ll be missing out on the things that make each device great, so you have to decide what the right design is for your app on each device
But you can share skills and tools and some code *where it makes sense*
When porting an app to a new platform, take a design-first approach: don’t just look at how to make the code run on the other platform, think about what is the right expression for your app on this device
tvOS:
Biggest, boldest screen
Often used together with friends
Used with Siri Remote, entire interface must be navigable using focus
Streamlined navigation
Rich, immersive experience – media, photos, videos, not performing tasks
Carefully consider which experiences make sense when viewed on a large screen
Here, we want to use: beautiful photos of landmarks, adding favorites, basic tourism information
We don’t want: lengthy historical information, advanced sorting & filtering, anything location-based
.focusable(canBecomeFocused) { isFocused … }
⭢ set if element should be focusable and react to focus
.onPlayPauseCommand { }
.onExitCommand { }
Don’t use long, vertically scrolled and nested lists of text, use a navigation UI that emphasizes content (pictures)
Take advantage of the big screen
On iOS, when using both a navigation controller and tab controller, the tab controller is the top level and a navigation controller may be used in one or more tabs, so that when you navigate deeper the tab bar is still visible
On tvOS, the tab controller should be added *inside* navigation controller, so that you see tabs at the top on the root level, but when you select some content, the tabs disappear
macOS:
High information density – a large screen with relatively small fonts, so you can show a lot of information
Higher tolerance for large amounts of text
Precision pointing device allows smaller click targets and denser controls (within reason!)
Multiple window support
Keyboard shortcuts
Touch Bar
SwiftUI automatically adjusts padding/spacing to be appropriate for the Mac
Use .controlSize()
for more compact controls
Menu item commands: (*)
view.onCommand(Selector(“showExplore:”)) { self.selectedTab = .explore }
Touch Bar:
view.touchBar(TouchBar { Button(action: show) { Image(…) } Button(action: delete) { Text(…) } })
To reuse the same container view between platforms but customize e.g. the row type class, you can parametrize the container with the row type and add a rowProvider
:
struct SharedLandmarksList<LandmarkRowType: View>: View { … var rowProvider: (Landmark) -> LandmarkRowType } struct MacLandmarksList: View { var body: some View { SharedLandmarksList() { landmark in return MacLandmarkRow(landmark: landmark) } } }
double click ⭢ onTapGesture(count: 2) { … }
(*)
watchOS:
A good rule is to aim for important actions to be reachable with 3 taps or less
.digitalCrownRotation
modifier
.listStyle(CarouselListStyle())
(*) – a scrolling list that focuses on each cell