问题
When I restored my purchases, I need to disabled the restore button in the view.
I have IAPManager
class with SKPaymentTransactionObserver
, and it works fine, I saw the print("restored")
of SKPaymentTransactionObserver when I call SKPaymentQueue.default().restoreCompletedTransactions
from my principal view.
So, then the problem is that from the view I do not find out about that event and therefore I cannot disable the button, since the purchase has already been restored.
In my IAPManager:
func restore(withUsername username: String? = nil) {
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().restoreCompletedTransactions(withApplicationUsername: username)
}
extension IAPManager: SKPaymentTransactionObserver {
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
transactions.forEach {
switch $0.transactionState {
case .purchasing: ()
print("purchasing")
case .deferred: ()
print("deferred")
case .restored: SKPaymentQueue.default().finishTransaction($0)
print("restaured")
UserDefaults.standard.set(true, forKey: "pro")
case .failed: SKPaymentQueue.default().finishTransaction($0)
print("failed")
UserDefaults.standard.set(false, forKey: "pro")
case .purchased: SKPaymentQueue.default().finishTransaction($0)
print("purchased")
UserDefaults.standard.set(true, forKey: "pro")
@unknown default:
break
}
}
}
In my View:
Text("Available purchases").font(.title3).foregroundColor(.green)
.onTapGesture {
IAPManager.shared.getProducts()
}.padding()
Spacer()
Button(action: {
let purchased = UserDefaults.standard.bool(forKey: "pro")
if !purchased {
print("Going to try restore")
IAPManager.shared.restore()
} else {
print("restored!")
}
}){
Text((buyed ? "Restored" : "Restore" ))
.fontWeight(.bold)
.font(.none)
.padding(6)
.cornerRadius(40)
.foregroundColor(.blue)
.overlay(
RoundedRectangle(cornerRadius: 40)
.stroke(Color.blue, lineWidth: 0.8)
)
}.buttonStyle(PlainButtonStyle())
.disabled( UserDefaults.standard.bool(forKey: "pro"))
.padding()
回答1:
For communication between unrelated and already existing components you can use custom Notifications.
- Create a name for your Notification:
extension IAPManager {
static let proNotification = Notification.Name(rawValue: "proNotification")
}
- In the place where you restore your transactions, send out the notification informing all subscribers that the Pro is restored:
case .restored:
print("restored")
SKPaymentQueue.default().finishTransaction($0)
NotificationCenter.default.post(name: IAPManager.proNotification, object: nil, userInfo: nil)
- Now you need a way to observe this notification::
struct ContentView: View {
@State var isPro = false
var body: some View {
Text(isPro ? "pro user" : "standard user")
.onReceive(NotificationCenter.default.publisher(for: IAPManager.proNotification)) { _ in
self.isPro = true
}
}
}
来源:https://stackoverflow.com/questions/63919916/storekit-delegate-observable-object-in-swiftui-view