StoreKit 2 - checkVerified is not async but it require await?

Viewed 135

I'm trying to follow Apple tutorial on StoreKit 2 and for some reason I'm getting "Expression is 'async' but is not marked with await. insert 'await'". It works if I add await, however the method is not async and in Apple tutorial the await is not used.

The issue is this line (this works in Apple tutorial but not in my code):

let transaction = try self.checkVerified(result)

This works in my example (however checkVerified is not async):

let transaction = try await self.checkVerified(result)

Here is the code example:

import SpriteKit
import StoreKit

typealias Transaction = StoreKit.Transaction

class SceneMenu: SKScene {
    
    private var storeProducts = [Product]()
    private var updateListenerTask: Task<Void, Error>? = nil
    
    override init(size: CGSize) {
        
        super.init(size: size)
        
        let btnBuy = SKLabelNode(text: "Buy Now")
        btnBuy.name = "btn_buy"
        btnBuy.fontSize = 20
        btnBuy.fontColor = SKColor.blue
        btnBuy.fontName = "Avenir"
        btnBuy.position = CGPoint(x: size.width / 2, y: size.height / 2)
        addChild(btnBuy)
        
        updateListenerTask = listenForTransactions()
        
    }
    
    required init?(coder aDecoder: NSCoder) {
        
        fatalError("init(coder:) has not been implemented")
        
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        if let touch = touches.first {
            
            let location = touch.location(in: self)
            let action = atPoint(location)
            
            if action.name == "btn_buy" {
                
                print("btn_buy")
                
                Task {
                    
                    await requestProducts()
                    
                    for product in storeProducts {
                        print(product.displayName)
                    }
                    
                    await buy()
                    
                }
                
            }
            
        }
        
    }
    
    func requestProducts() async {
        
        do {
            let productIds = ["com.product.ticket-5", "com.product.ticket-10"]
            storeProducts = try await Product.products(for: productIds)
        } catch {
            print("Failed product request: \(error)")
        }
        
    }
 
    enum StoreError: Error {
        case failedVerification
    }
    
    func purchase(_ product: Product) async throws -> Transaction? {
        
        let result = try await product.purchase()
        
        switch result {
        case .success(let verification):
            let transaction = try checkVerified(verification)
            await transaction.finish()
            return transaction
        case .userCancelled, .pending:
            return nil
        default:
            return nil
        }
        
    }
    
    func buy() async {
        
        let product = storeProducts[0]
        
        do {
            if try await purchase(product) != nil {
                print("buying1")
            }
        } catch {
            print("Failed purchase for \(product.displayName): \(error)")
        }
        
    }
    
    deinit {
        updateListenerTask?.cancel()
    }
    
    func listenForTransactions() -> Task<Void,Error> {
        
        return Task.detached {
            for await result in Transaction.updates {
                do {
                    let transaction = try self.checkVerified(result)
                    print("buying2")
                    await transaction.finish()
                } catch {
                    print("Transaction failed verification")
                }
            }
        }
        
    }
   
    
    func checkVerified<T>(_ result: VerificationResult<T>) throws -> T {
        
        switch result {
        case .unverified:
            throw StoreError.failedVerification
        case .verified(let safe):
            return safe
        }
        
    }
 
}
1 Answers

There's no actual issue here, but if you don't want to have to say await, change

func checkVerified...

To

@MainActor func checkVerified...

This may have additional knock-on effects but just keep doing that.

Related