This UIKit sample code demonstrates ease of use for SwiftTipJar - an open source package.
There is also SwiftUI sample code (same functionality).
Tip jars on Apple platforms are a concept of letting users make in-app purchases to show appreciation for the app/developer. These don't actually unlock any additional features.
Choice of tips | System UI for purchasing | Successful purchase | Thank you message |
---|---|---|---|
- Init TipJar with identifiers for In-App Purchases you wish to offer
- Make TipJar observe StoreKit's payment queue
- Set up code blocks to run after products information is received - from Xcode (when using StoreKit Configuration file) or from App Store Connect over the network - and after a transaction succeeds or fails.
- Request the products information
// #1
let tipJar = SwiftTipJar(tipsIdentifiers: Set(["com.test.smallTip", "com.test.mediumTip", "com.test.largeTip", "com.test.hugeTip"]))
override func viewDidLoad() {
super.viewDidLoad()
// #2
tipJar.startObservingPaymentQueue()
// #3
tipJar.productsReceivedBlock = setupButtons
tipJar.transactionSuccessfulBlock = showThankYou
// #4
tipJar.productsRequest?.start()
}
- As soon as tipJar finds out about the products, it runs publishes tips, an array of Tip objects that supplies you with displayName and displayPrice, in local language and currency, and runs productsReceivedBlock. Tips array has been sorted by price, ascending. Products that haven't been configured with a name and/or price are simply omitted from this array.
@Published public private(set) var tips: [Tip] = []
public final class Tip {
public var identifier: String = ""
public var displayName: String = ""
public var displayPrice: String = ""
/// TipJar uses this to quickly check if it should include this Tip in its published array.
var isValid: Bool {
return !identifier.isEmpty && !displayName.isEmpty && !displayPrice.isEmpty
}
}
- Assign any code you want to run after a successful purchase to transactionSuccessfulBlock, and similarly any code you want to run after a failed purchase (user clicked Cancel instead of Purchase) to transactionFailedBlock. With tip jars, it's even natural to do nothing if a transaction fails.
- Set up button(s) to initiate a purchase to trigger the action initiatePurchase(productIdentifier:)
@objc func userDidTapButton(_ sender: UIButton?) {
guard let identifier = sender?.accessibilityIdentifier else { return }
tipJar.initiatePurchase(productIdentifier: identifier)
}
Q: I've set up IAPs in a StoreKit Configuration file, but nothing is showing up in the demo app
A: Edit Scheme > Options, and check that you have the correct StoreKit Configuration selected
Q: I've set up IAPs in StoreKit Configuration file, some are showing up in demo app, but not all
A: Check that TipJar's init is called with all relevant identifiers; check identifiers for any spelling errors. Check that you've provided the name and price for every IAP you want to see in the demo app.