Skip to content

Instantly share code, notes, and snippets.

@frankschlegel
Last active September 4, 2023 07:51
Show Gist options
  • Save frankschlegel/a7afb1f687d7793afc58553a1268cb03 to your computer and use it in GitHub Desktop.
Save frankschlegel/a7afb1f687d7793afc58553a1268cb03 to your computer and use it in GitHub Desktop.
Working with TipKit when still supporting iOS 16 and below
import TipKit
/// Small helper protocol for a tip that is available below iOS 17
/// so that we can pass tips around and have members storing tips
/// (as stored properties can't be marked with `@available`).
@available(iOS, obsoleted: 17, message: "Can be removed once we only support iOS 17+")
public protocol TipShim {
@available(iOS 17, *)
var tip: AnyTip { get }
}
@available(iOS 17, *)
public extension Tip where Self: TipShim {
var tip: AnyTip { AnyTip(self) }
}
public extension View {
/// Helper for making the `popupTip` modifier available for iOS <17.
@available(iOS, obsoleted: 17, message: "Can be removed once we only support iOS 17+")
@ViewBuilder func popupTipShim(_ tipShim: TipShim?, arrowEdge: Edge = .top) -> some View {
if #available(iOS 17, *), let tip = tipShim?.tip {
self.popoverTip(tip, arrowEdge: arrowEdge)
} else {
self
}
}
}
@frankschlegel
Copy link
Author

frankschlegel commented Aug 31, 2023

You only need to have your tips conform to TipShim, and you can freely store them in a member or pass them to a method as a TipShim:

struct MyTip: Tip, TipShim {
    // ...
}

struct MyView {

    let tip: TipShim?

    var body: some View {
        Button(...)
            .popupTipShim(self.tip)
    }

}

struct OtherView {

    let tipOnButton: TipShim? = if #available(iOS 17, *) { MyTip() } else { nil }

    var body: some View {
        MyView(tip: self.tipOnButton)
    }

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment