Kuba Suder's blog on Mac & iOS development


App ClipsAppKitCloudKitExtensionsFoundationiCloudLocationLoggingMacMapsPerformancePhotosPrivacySafariSwiftSwiftUIUIKitWatchKitWWDC 12WWDC 14WWDC 15WWDC 16WWDC 18WWDC 19WWDC 20WWDC 21

View as index

SwiftUI on watchOS

Categories: SwiftUI, WatchKit, WWDC 19 0 comments Watch the video

SwiftUI offers apps some capabilities that were not possible before, e.g. swipe to delete and reordering in lists, or an easy way to do custom graphics and animations

Fully integrated with WatchKit, both ways

SwiftUI allows you to use the same code on all platforms

However, Apple Watch is a very special platform; a watchOS app should not be just a tiny version of the iOS app, it should be specifically designed for the Watch by only picking the right elements of the experience

Building an Apple Watch app is building the whole experience, not just the main app, but also complications, notifications, Siri interface – depending on the app

Use subclasses of WKHostingController to embed SwiftUI views in an interface controller that WatchKit can use

.font(.system(.headline, design: .rounded)) – uses a rounded version of San Francisco

.listRowPlatterColor(topic.color) – sets the color of the list cell background

.listStyle(.carousel) – a list design which centers the currently focused item on the screen

.onMove { } – enables drag to reorder

.onDelete { } – enables swipe to delete

For notification UI, inherit from WKUserNotificationHostingController

When a notification is received (didReceive(_:)), the view body is automatically invalidated and reloaded

Using digital crown:

Fluent scrolling between the beginning and the end:

.digitalCrownRotation($binding, from:, through:)

→ lets you create some kind of custom scrollable container

Discrete values:

.digitalCrownRotation($binding, from:, through:, by:)

→ for building interfaces where e.g. some value moves up or down by 1 when scrolling

Going around in a circle:

.digitalCrownRotation($binding, from:, through:, by:, sensitivity:, isContinuous: true)

→ sensitivity says how fast it rotates

.focusable(true) – lets the user switch focus between elements; digital crown events go to the focused item

What's new in watchOS design

Categories: WatchKit, WWDC 20 0 comments Watch the video

Watch apps should be:

  • lightweight – limit the amount of functionality that you make available in the Watch app
  • actionable
  • discoverable – make important actions easy to find

All actions that were previously hidden inside Force Touch menus have now been moved into the main views of their apps (e.g. Activity settings, Weather modes, Mail’s new message)

Where to put such secondary actions now?

Sorting (example from Activity): a button at the top / first table cell that opens a modal with a sorting mode selection

View switcher (example from Stocks): a button at the top that opens a modal which lets you choose if you want to see points/percentages/market cap

→ in SwiftUI – Picker()

Swipe actions (World Clock): a delete button when you swipe a row, an add button at the bottom

→ SwiftUI: .onDelete()

Actions in a full screen view like Maps or Camera: a “more” button in the corner that opens a modal with a list of actions or options

→ SF symbol “ellipsis”

If there’s only one action, just make a button with an icon of that action (Photos app)

→ white circle at 85% opacity, 1pt black outer glow at 50% opacity

“More” button inside table cells – Workouts app

→ don’t put primary actions inside “More” menus!

Action buttons at the bottom of a scroll view – Calendar app:

  • on an invite page, buttons to accept/decline an event or to email the sender
  • on your own event, a button at the bottom to delete the event
  • for destructive actions, make the label text red and add a confirmation dialog

New “toolbar” button (Messages) – a button that appears at the top only when you scroll up, but is initially hidden

→ SwiftUI: .toolbar()

Switching between folders or groups (Mail, Home) – hierarchical navigation where you start inside a default folder, but can move up to root level

Creating Independent Watch Apps

Categories: WatchKit, WWDC 19 0 comments Watch the video

Watch apps can now be independent – iPhone app is now optional

Up to watchOS 5, the Watch app was embedded in the iOS app and both were downloaded to the iPhone. iPhone then handled the task of installing the Watch app to the Watch.

Now, in iOS 13 and watchOS 6, both apps are installed straight from the App Store directly on the relevant device, each device installs its own app. This applies to all apps in the store today. iOS app no longer has the Watch app bundled inside, it no longer counts towards your iOS app cellular download limit if you don't need it.

This also enables asset/variant thinning for Watch apps – if you have a Series 4 watch, only Series 4 assets are downloaded to the watch (previously the iOS app had to include all variants in the bundled Watch app for any possible watches).

All current apps belong to the category of “dependent apps”, i.e. the Watch app depends on the iOS app. If you install a dependent app on the Watch, the iPhone will automatically install the matching companion iOS app. (Watch app launch is blocked until the iOS app is installed.)

On the other hand, independent apps can live without their iOS counterpart installed. They are backwards-compatible with earlier OSes.

→ to make an app independent, check the checkbox “Supports Running Without iOS App Installation”

Watch-only apps – apps that do not even have an iOS counterpart – are also possible, they require watchOS 6.

Debugging in the simulator is now up to 10x faster, on the device up to 2x faster

Added text field control (WKInterfaceTextField) to let you implement sign in forms

Use WKAlertAction for terms & conditions

Sign In With Apple button (AuthenticationServices, WKInterfaceAuthorizationAppleIDButton)

Continuity keyboard for Watch ⭤ iOS – you can e.g. enter passwords to log in on the watch using your iOS device

For proper handling of logging in, set textContentType and associated domains

Getting health authorization is now also supported on watchOS

Watch is now a standalone push target, you can send user-visible notifications and background notifications straight to the watch

New APNs request header – apns-push-type: set to alert for user-visible notifications, and background for background notifications

→ required for watchOS

Notification service extension support for e.g. decrypting notifications

Complication pushes can also be sent straight to the watch (PushKit)

Networking: use URLSession, CloudKit

  • make sure to use background sessions
  • full CKSubscription / CloudKit notifications support

It’s preferred to use URLSession than WatchConnectivity

  • WC is still available for any iOS-to-watchOS specific communication, but only use it if you really need to
  • check isCompanionAppInstalled