Displaying tips based on parameters and events with TipKit

Displaying tips based on parameters and events with TipKit

Learn how to trigger tips based on parameters and events with TipKit in a SwiftUI app.

In the tutorial Using TipKit on a SwiftUI app, we saw how helpful the TipKit framework is to help users discover our app's main feature. Now let's set up the tips so they are displayed after specific user interactions using Parameter and Event rules.

Remember that to display tips you must first configure the application tips with the Tips.configure() method and when testing your tips use the Tips.resetDatastore() method to reset any dismissal state.

Showing the tips using parameter rules

Consider the case where you want to display a specific tip after the user interacts with a button or performs a particular action. We can define a property inside the tip declaration that allows us to present it only after a certain condition is met.

A type that monitors the state of its wrapped value to reevaluate any dependent tip rules when the value changes.

Using the @Parameter property wrapper we can monitor the state of a value to reevaluate the rules of a tip. After that, we can add a Rule inside our tip using the #Rule macro to set the condition for presenting the tip inside the app.

import TipKit

struct ParameterRuleTip: Tip {
    
    // Value to be tracked to reevaluate the Rules
    @Parameter
    static var isTipPresented: Bool = false
    
    // Rules to control when a tip is displayed
    var rules: [Rule] {
        [
            #Rule(Self.$isTipPresented) {
                $0 == true
            }
        ]
    }
    
    var title: Text {
        Text("Parameter Rule")
    }
    
    var message: Text? {
        Text("You can present this tip only when the property is true")
    }
    
    var image: Image? {
        Image(systemName: "swift")
    }

}

In the example above the tip will be shown in the app only when the isFavoritePressed property is set to true. We can access this property inside the View and display the tip using the TipView component.

import SwiftUI
import TipKit

struct ContentView: View {
    
    let parameterRuleTip = ParameterRuleTip()
    
    var body: some View {
        
        VStack {
            // Tip to be presented
            TipView(parameterRuleTip)
                .padding()
            
            Button {
                // Toggling the parameter value
                ParameterRuleTip.isTipPresented.toggle()
            } label: {
                Text("Show a tip")
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()

        // For testing purposes
        .onAppear {
            try? Tips.resetDatastore()
            try? Tips.configure()
        }
        
    }
}

Clicking on the button the user will visualize the tip that we defined.

Showing the tips based on events

You can also consider showing your tip only after a user accesses a particular view many times. It can be useful to bring awareness to a feature on that view the user isn't aware of. We can define this type of rule using the Event type.

Using Event we can monitor actions occurring one or multiple times within the app. Each time the action happens, we'll "donate" to the event, incrementing its count by one. This count will then determine whether the associated tips should be presented.

struct EventRuleTip: Tip {
    
    static let eventVisualized = Event(id: "eventVisualized")
    
    var title: Text {
        Text("Event Rule tip")
    }
    
    var message: Text? {
        Text("This tip is presented after the donation count is bigger than 3")
    }
    
    var image: Image? {
        Image(systemName: "3.circle")
    }
    
    var rules: [Rule] {
        [
            #Rule(Self.eventVisualized) {
                $0.donations.count > 3
            }
        ]
    }
    
}

In the example above, the tip will be presented when the donation count of the event is greater than three. In other words, the tip will be displayed after the fourth time the user accesses the same view.

We can donate to the event on our View using the onAppear(perform:) modifier and calling the donate() method from the eventVisualized property.

import SwiftUI
import TipKit

struct ContentView: View {
    
    @State var showView: Bool = false
    
    var body: some View {
        
        Button {
            showView.toggle()
        } label: {
            Text("Show the view!")
        }
        
        .sheet(isPresented: $showView, content: {
            VisualizedView()
        })
        
        // For testing purposes
        .onAppear {
            try? Tips.configure()
        }
        
    }
}

struct VisualizedView: View {
    
    var eventRuleTip = EventRuleTip()
    
    var visualizations: Int {
        EventRuleTip.eventVisualized.donations.count + 1
    }
    
    var body: some View {
        
        VStack {
            Text("Hello!").font(.title2).bold()
            
            Text("You saw me **\(visualizations)** times")

            TipView(eventRuleTip)
                .padding()
        }
        
        .onAppear {
            Task {
                await EventRuleTip.eventVisualized.donate()
            }
        }
    }
}