Starting in iOS 18 you can sync the state of TipKit tips across devices with CloudKit.
TipKit Tip State
Apple introduced TipKit in iOS 17 as a consistent way to show in-context tips to users. TipKit keeps track of how often it displays tips, when it has invalidated tips, and the events/rules that control when it should show tips.
Starting in iOS 18, you can opt-in to syncing the TipKit state across devices using CloudKit. That avoids showing the user the same tips on each of their devices.
Syncing With CloudKit
Enabling CloudKit sync for TipKit follows a similar process to enabling sync for Core Data.
-
Select your App target in Xcode. In the Signing & Capabilities tab, use the + Capability button, double-click the iCloud capability and select CloudKit in the iCloud section. This also adds the Push Notifications capability:
-
In the iCloud capability section, use the + button, below the list of containers, to add a container identifier for the TipKit datastore:
Use a reverse domain name to create the identifier, ending with “.tips”. Xcode automatically includes the “iCloud” prefix. The new container can take a few seconds to show up in the iCloud console. Xcode shows the identifier in red until it’s ready:
-
Repeat the process to add the Background Modes capability to your App target and enable the Remote notifcations option:
TipKit does not sync to CloudKit by default. You must enable the CloudKit container when configuring the Tips datastore:
try Tips.configure([
.cloudKitContainer(.automatic)
])
Note:
- The
.automatic
option uses the first container in your app’s entitlements that ends with “.tips”. You can override the automatic behaviour by passing an identifier:
try Tips.configure([
.cloudKitContainer(.named("iCloud.com.apple.myapp.tips"))
])
Core Data Container Identifier
Be careful if you’re already syncing a Core Data/SwiftData database with CloudKit. By default, NSPersistentCloudKitContainer
looks for the first iCloud Container identifier in the App’s entitlements file. If you’re not careful you may have listed your TipKit identifier first and your Core Data stack can end up trying to use it.
Apple recommends you use a separate container for syncing tips.
As a workaround, make sure to list your Core Data/SwiftData identifier first in the entitlements file:
Alternatively you can explicitly set the container identifier before loading the persistent store when creating your Core Data stack:
storeDescription.cloudKitContainerOptions =
NSPersistentCloudKitContainerOptions(
containerIdentifier: "com.useyourloaf.myapp")
Learn More
One More Thing
If you’re working with UIKit and want to brush up your layout skills make sure to grab a copy of my book Modern Auto Layout. It’s 20% off in the WWDC25 sale!.