I'm trying to utilize Apple's new TipKit where I still support iOS16. Is there a way to initialize the Tip without making the entire struct as @available(iOS 17, *). Example being
struct MainHomeEntryView: View {
var myTip = MyTip()
....
}
error: 'SubmitTip' is only available in iOS 17 or newer
We had the same problem and came up with this small helper:
import SwiftUI
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
}
}
}
With it, you only need a minimal amount of if #available checks. You only have to let your tip conform to TipShim:
struct MyTip: Tip, TipShim {
// no additional implementation required,
// as this was done in the extension above
}
and then you can use it like this:
struct MainHomeEntryView: View {
var myTip: TipShim?
init() {
if #available(iOS 17, *) {
self.myTip = MyTip()
}
}
var body: some View {
MyView()
.popupTipShim(self.myTip)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With