Intelligently educate your users about the right features at the right time with TipKit

Posts under TipKit tag

50 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

TipView can't show
import SwiftUI import TipKit struct ChatRoomView: View { @StateObject private var socketManager = SocketIOManager() @State private var inputText: String = "" @StateObject var viewModel = SignInWithAppleViewModel() @Binding var isCall: Bool @State private var isSheet = false @State private var ShowView = false var learnlisttip = KeyTip() @Binding var showShareSheet: Bool @Binding var codeshar: String var body: some View { NavigationStack{ VStack { if let roomCode = socketManager.roomCode { ZStack{ VStack{ HStack{ Text("Room Key: \(roomCode)") .font(.title) .onAppear{ codeshar = roomCode self.isCall = true } Button(action:{ self.showShareSheet = true }, label:{ Image(systemName: "square.and.arrow.up.fill") .accessibilityLabel("Share") }) } .padding(20) TipView(learnlisttip, arrowEdge: .top) .glassBackgroundEffect() .offset(z: 20) Spacer() } List(socketManager.messages, id: \.self) { message in Text(message) } TextField("input", text: $inputText) Button("send") { socketManager.sendMessage(roomCode: roomCode, message: inputText) inputText = "" } } .sheet(isPresented: $showShareSheet) { let shareContent = "Open SpatialCall, Join this Room, Key is: \(codeshar)" ActivityView(activityItems: [shareContent]) } } else { HStack{ Button(action:{ withAnimation{ socketManager.createRoom() } }, label: { VStack{ Image(systemName: "phone.circle.fill") .symbolRenderingMode(.multicolor) .symbolEffect(.appear, isActive: !ShowView) .font(.largeTitle) Text("Add Room") .font(.title3) } }) .buttonStyle(.borderless) .buttonBorderShape(.roundedRectangle) .padding(.horizontal, 30) .glassBackgroundEffect() .offset(z: 20) .scaleEffect(1.5) .padding(60) Button(action:{ withAnimation{ self.isSheet = true } }, label: { VStack{ Image(systemName: "phone.badge.checkmark") .symbolRenderingMode(.multicolor) .symbolEffect(.appear, isActive:!ShowView) .font(.largeTitle) Text("Join Room") .font(.title3) } }) .buttonStyle(.borderless) .buttonBorderShape(.roundedRectangle) .padding(.horizontal, 30) .glassBackgroundEffect() .offset(z: 20) .scaleEffect(1.5) .padding(70) } } } .onAppear { DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { withAnimation { self.ShowView = true } } } .sheet(isPresented: $isSheet){ VStack{ Text("Join Room") .font(.largeTitle) Text("You need to get the key to the room.") TextField("Key", text: $inputText) .padding(30) .textFieldStyle(.roundedBorder) Button(action:{ socketManager.joinRoom(roomCode: inputText) self.isSheet = false }, label: { Text("Join Room") .font(.title3) }) .padding(50) } .padding() } .sheet(isPresented: $socketManager.showRoomNotFoundAlert) { Text("The room does not exist. Please check whether the Key you entered is correct.") .font(.title) .frame(width: 500) .padding() Button(action:{ self.socketManager.showRoomNotFoundAlert = false }, label: { Text("OK") .font(.title3) }) .padding() } } } } In the above code (this is a visionOS project), when I click Share, it can't display Sheet normally, and TipView can't be displayed either. Why?
1
0
613
Jan ’24
TipKit Tip popover only shows one time.
try Tips.resetDatastore() try Tips.configure( [ // Reset which tips have been shown and what parameters have been tracked, useful during testing and for this sample project .datastoreLocation(.applicationDefault), // When should the tips be presented? If you use .immediate, they'll all be presented whenever a screen with a tip appears. // You can adjust this on per tip level as well .displayFrequency(.immediate) ] ) struct UserTip: Tip { static let hoverEvent: Event = Event(id: "hoverEvent") @Parameter var isHovering: Bool = false static var tipCountKey = "UserTipCount" var title: Text var message: Text? var image: Image? var tipShownLimit: Int var options: [Option] { // Show this tip 5 times. [ Tips.MaxDisplayCount(5), Tips.IgnoresDisplayFrequency(true) ] } var rules: [Rule] { #Rule($isHovering) { $0 == true } } } struct ShowPopoverTip: View { @State private var tip = UserTip( title: Text("the title"), message: Text("the message here"), image: Image(systemName: "volleyball.fill"), tipShownLimit: 10 ) var body: some View { Button(action: { }) { Text("Hover over me") } .popoverTip(tip) .onAppear { } .onHover { hovering in if hovering { tip.isHovering = true print("tip.status: \(tip.status)") print("tip.isHovering: \(tip.isHovering)") print("tip.shouldDisplay: \(tip.shouldDisplay)") }else{ tip.isHovering = false print("tip.isHovering: \(tip.isHovering)") } } } } The popover only works once, even though I have set it to Tips.MaxDisplayCount(5) Either the Tip is getting invalidated or popovers only show once. debug output: tip.isHovering: true tip.shouldDisplay: false tip.isHovering: false tip.status: pending tip.isHovering: true tip.shouldDisplay: false tip.isHovering: false btw, if I remove the Tips.resetDatastore(), it still shows once each time I launch the app.
1
0
821
Jan ’24
TipKit Rule won't compile
static let hoverEvent: Event = Event(id: "hoverEvent") /// Parameters-Rules @Parameter static var isHovering: Bool = false static var tipCountKey = "UserTipCount" var title: Text var message: Text? var image: Image? var tipShownLimit: Int @ObservedObject var buttonState: ButtonState var rules: [Rule] { #Rule(Self.hoverEvent) { $0.donations.count < tipShownLimit } } } error: Event Rules require a count comparison. If I replace tipShownLimit like this: var rules: [Rule] { #Rule(Self.hoverEvent) { $0.donations.count < 3 } } it compiles fine. the error is: Event Rules require a count comparison.
2
0
495
Jan ’24
Reset specific tip
If I have some tips in an onboarding flow and want to allow my user to restart the onboarding experience, how can I reset specific tips? I know there is Tips.resetDatastore() but I may not want to reset every tip, just some subset of them.
2
1
590
Jan ’24
arrowEdge of popoverTip not working anymore on iOS 17.1
In iOS 17.1 (and 17.2 beta), the arrowEdge parameter of the SwiftUI popoverTip doesn't work anymore. This code button .popoverTip(tip, arrowEdge: .bottom) looks like this on iOS 17.0 and like this on 17.1 and up. I checked permittedArrowDirections of the corresponding UIPopoverPresentationController (via the Memory Graph): It's .down on iOS 17.0 and .any (the default) on 17.1. It seems the parameter of popoverTip is not properly propagated to the popover controller anymore.
2
1
720
1w
Custom styles for popovertips
Hi. We want to implement TipKit, and specifically popovertips, in our app but it does not seem to be a way to customize these as you can with TipView and custom TipViewStyles. I noticed the documentation references MiniTipStyle but it only contains the standard minitipStyle. Is there a way to fully customize popovertips or is it coming in a future update? Best regards Johannes
4
0
947
Nov ’23
Tipkit Tips keep popping up after invalidation
I'm using UIKit and setting up TipKit with the suggested defaults try? Tips.configure([ .displayFrequency(.immediate), .datastoreLocation(.applicationDefault) ]) within func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { } Every time I swipe out of the app the tips start reappearing again - even the ones that have been invalidated. Has this happened for anyone else and does anyone else have a solution? Here's an example of one of my tips struct createTabTipHomePage: Tip { var title = styleTipTitle("Title") var message = styleTipMessage("Message") var asset: Image { Image(systemName: "plus.square") .resizable() } var rules: [Rule] { [ #Rule(TipActions.$homeTrandingScrolledToCreateTrigger) { $0 == true } ] } var options: [TipOption] { [Tip.MaxDisplayCount(1)] } func showAction() { TipActions.homeTrandingScrolledToCreateTrigger.toggle() } }
5
1
865
Nov ’23
TipKit with NavigationSplitView
I'm facing multiple issues with TipKit. Let's start with this one. It's a NavigationSplitView, side bar has a toolbar button with a .popoverTip as well as the detail view. When launched (iPad landscape for example) only the sidebar tip shows, which is understandable because you wouldn't want two tips to show. However when the sidebar tip is .invalidate the second tip doesn't show. One needs to restart the app. How can I show the detail tip after the sidebar tip has been .invalidate? import SwiftUI import TipKit @main struct TestApp: App { let firstTip = FirstTip() let secondTip = SecondTip() var body: some Scene { WindowGroup { NavigationSplitView { List(1..<3) { i in NavigationLink("Row \(i)", value: i) } .toolbar { ToolbarItem { Button { firstTip.invalidate(reason: .actionPerformed) } label: { Image(systemName: "fireworks") } .popoverTip(firstTip, arrowEdge: .top) } } .navigationDestination(for: Int.self) { Text("Selected row \($0)") } .navigationTitle("Split View") } detail: { Text("Please select a row") .toolbar { ToolbarItem { Button { secondTip.invalidate(reason: .actionPerformed) } label: { Image(systemName: "trash") } .popoverTip(secondTip, arrowEdge: .top) } } } } } init() { try? Tips.resetDatastore() try? Tips.configure([ .datastoreLocation(.applicationDefault), .displayFrequency(.immediate) ]) } } struct FirstTip: Tip { var title: Text {Text("FirtTip")} var message: Text? {Text("FirtTip")} var image: Image? {Image(systemName: "trash")} } struct SecondTip: Tip { var title: Text {Text("SecondTip")} var message: Text? {Text("SecondTip")} var image: Image? {Image(systemName: "trash")} }
1
0
610
Oct ’23
Bug: Tip comes back as pending first, then available when reloading screen
When loading screen, I scan for tips: private lazy var scanAreaTipTask = Task { @MainActor in for await shouldDisplay in scanAreaTip.statusUpdates { if shouldDisplay == .available { onSetBeacon.send(.scanArea(scanAreaTip, .show)) } else { onSetBeacon.send(.scanArea(scanAreaTip, .hide)) scanAreaTipFinished = true } } } Task is called in ViewDidAppear of the UIViewController. First time I load this view controller, the scanAreaTip.statusUpdates always comes back as pending. If I quit this view controller and open it again, the scanAreaTip.statusUpdates will come back as available. Why does it always come back as pending on the first opening where it should come back as available? This is the tip that I am using. As shown, there aren't any rules or options used. Just a plain tip that should show straight away. public struct ScanAreaTip: Tip { public init() {} public var title: Text { Text("Scan area around you") .brandFont(style: .regular(.headline)) .foregroundStyle(Color.accentColor) } }
1
0
522
Oct ’23
TipUIPopoverViewController disables all the views from presenting screen
when using Tips with UIKit, presenting TipUIPopoverViewController disables all the buttons from the presenting screen. I assume this is the expected behaviour but is there a way to disable it? I would like the button that the tip is pointing to to be still enabled. Otherwise user has to tap on it twice which is not ideal. Method checking for tip's eligibility. private extension MenuViewController { func activateTips() { Task { @MainActor [weak self] in guard let self else { return } for await shouldDisplay in createMapTip.shouldDisplayUpdates { if shouldDisplay { let controller = TipUIPopoverViewController(createMapTip, sourceItem: createMapButton) { [weak self] action in if action.id == "LearnAboutMaps" { if self?.presentedViewController is TipUIPopoverViewController { self?.dismiss(animated: true) { self?.createMapTip.invalidate(reason: .actionPerformed) self?.viewModel.handle(.didTapLearnMoreAboutMaps) } } } } present(controller, animated: true) } else if presentedViewController is TipUIPopoverViewController { dismiss(animated: true) } } } } }
2
0
651
Oct ’23
Dismiss Tip
Is it possible to disable the ability for the user to dismiss a tip? If not, is there a way to activate a tip again after it has been dismissed? Can the tip status be reset without deleting the datastore? I want to show a tip for password help after 3 failed login attempts but I never want it to be invalidated by the user.
3
1
875
Oct ’23
Multiple PopoverTip Modifiers in SwiftUI: Persistent Display Glitch
Hello! I've encountered an issue when attempting to add multiple popoverTip modifiers in my SwiftUI code. Regardless of whether there's a specified rule or parameter, the tips begin to constantly appear and disappear. Is this a recognized issue? How can we sequentially display multiple tip popovers on complex views? Even when one tip is invalidated, the glitch persists. Should this be used only for views without any state updates? Here's a sample code that demonstrates the problem: import SwiftUI import TipKit @main struct testbedApp: App { var body: some Scene { WindowGroup { ContentView() } } init() { try? Tips.configure() } } struct PopoverTip1: Tip { var title: Text { Text("Test title 1").foregroundStyle(.indigo) } var message: Text? { Text("Test message 1") } } struct PopoverTip2: Tip { var title: Text { Text("Test title 2").foregroundStyle(.indigo) } var message: Text? { Text("Test message 2") } } struct ContentView: View { private let timer = Timer.publish(every: 0.001, on: .main, in: .common).autoconnect() @State private var counter = 1 var body: some View { VStack(spacing: 20) { Spacer() Text("Counter value: \(counter)").popoverTip(PopoverTip1()) Spacer() Text("Counter value multiplied by 2: \(counter * 2)") .foregroundStyle(.tertiary) .popoverTip(PopoverTip2()) Spacer() } .padding() .onReceive(timer) { _ in counter += 1 } } } #Preview { ContentView() }
2
1
899
Sep ’23
SwiftUI: popoverTip prevents other modal views from appearing
I want to show a tip on a button that will open a modal sheet on tap. The state if the sheet should be presented is held in an ObservableObject view model: @MainActor class ViewModel: ObservableObject { @Published var showSheet = false } struct ContentView: View { var tip = PopoverTip() @ObservedObject var viewModel = ViewModel() var body: some View { Button(action: { viewModel.showSheet.toggle() }, label: { Text("Button") }) .popoverTip(tip) .sheet(isPresented: $viewModel.showSheet) { Text("Sheet") } } } Here is the issue: When the tip is dismissed by tapping outside of it instead of tapping the close button, the tip will always reappear when tapping the button instead of showing the sheet. So effectively there is no way of triggering the actual button action, the tip will always pop up again and prevent the sheet from appearing. This is only an issue when using an ObservableObject to track the sheet state. When using a @State var showSheet: Bool inside the view itself instead, the sheet is shown as expected when tapping the button. It seems to be an issue of timing: Attempting to show the sheet somehow causes the view to be re-evaluated, which causes the tip to reappear (since it wasn't dismissed via close action). And since the tip is presented using modal presentation, the sheet can't be presented anymore. Is this a bug, or is there a simple way to avoid this issue?
3
3
1.3k
Oct ’23
TipKit not showing via TestFlight
My TipKit views are showing in Previews, when I run on a Simulator, and on a physical device (running iOS 17 Beta), but if I archive and upload to TestFlight, I do not see them (on devices running iOS 17 Beta)... Anyone else encounter this? I am using the Xcode 15 GM (15A240d). I tried manually adding the framework into the target. I am worried that if I submit for Review it will not show on devices when released... Am I just supposed to trust that it will work via the App Store? 🫣
13
3
1.8k
Nov ’23
TipKit Image asset tint color
Hello, I have a simple tip that im displaying, but want to change the tint color to something other than the default system blue tint. I tried different approaches that are common in changing image tint color but none seem to work. Is there a special call to achieve that? Note: I'm using UIKit to display the tip. Version 15.0 beta 8 (15A5229m) Thank you! example tip: struct FavoriteTip: Tip { var title: Text { Text("Favorite This Car") } var message: Text? { Text("Favorite this car to receive status updates and more!") } var image: Image? { Image(systemName: "heart.fill") } }
4
0
1.5k
Oct ’23
Popover tips not affected by tip view modifiers
Tips presented using the popoverTip view modifier can't be styled using other tip view modifiers (as of beta 8). For instance, the last two modifiers don't have any effect here: Image(systemName: "wand.and.stars") .popoverTip(tip) .tipBackground(.red) .tipCornerRadius(30) It will look like this: Whereas applying the same modifiers to a TipView changes its look: TipView(tip, arrowEdge: .bottom) .tipBackground(.red) .tipCornerRadius(30) Is this intended behavior? How can we change the appearance of popup tips?
2
0
930
Sep ’23