iostipkit

Tip.statusUpdates doesn't fire on event donation


I have a tip that's supposed to be shown after a certain event:

extension Tips {
    static let somethingHappened = Tip.Event(id: "somethingHappened")
}

struct TestTip: Tip {
    let title = Text("Test tip")
    let message = Text("This is a description")

    var rules: [Rule] {
        #Rule(Tips.somethingHappened) { $0.donations.count > 0 }
    }
}

I would like to present this tip when its status becomes .available. To do this, I'm observing statusUpdates in a task:

tipStatusObserverTask = Task { [tip, weak self] in
    print("observing \(tip.id)")

    for await status in tip.statusUpdates {
        guard let self, !Task.isCancelled else {
            return
        }

        print("tip status: \(status)")

        if case .available = status {
            print("will present \(tip.id)")
            displayTip()
        }
    }

    print("done observing \(tip.id)")
}

then I'm donating the event on a button press:

@objc func didPressButton() {
    Tips.somethingHappened.sendDonation {
        print("donated Tips.somethingHappened")
    }
}

The event is donated, but statusUpdates doesn't fire, so the tip never gets shown. The tip appears after I restart the app. What's happening? What am I doing wrong?

statusUpdates fires just fine if the rule is based on a @Parameter change, so I would expect this approach to work for event-based rules.

Here's a project that reproduces the issue in case anyone wants to try: https://www.icloud.com/iclouddrive/085FxcgTPStDSSPoXwh7dx1pQ#TipKitTest

Update: This is likely a bug, I have filed a radar: FB16040974


Solution

  • I believe you're missing configurations. Try to put these code before setting up tipStatusObserverTask

    private func setupTips() throws {
        try Tips.resetDatastore()
        try Tips.configure()
    }
    

    Edit: As you mentioned, it could be an iOS 18 bug. I've read the release notes and update for TipKit. However, there is no information about how Apple changes the #Rule or something. So, fire a report is the only option, I guess.