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()
}
It would seem so. You can certainly get it to work by avoiding updates in the view that is showing the tips.
It works with the following changes:
ObservableObjectthat is created (but not observed) in the parent view.Textviews to separate views and pass them the wrapped counter to observe.With just these changes to your original code, it works to the extent that tip 1 is shown every time you restart the app, but tip 2 is never shown. In order that tip 1 is recorded as seen, you need to add a tap gesture that invalidates the tip, as explained in the documentation. Then, the next time you start the app, tip 2 is shown.
Here is your example with all the changes applied:
To reset all tips (for testing purposes), add a line to purge the tips to the
initfunction of the app, beforeTips.configure():