Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

515
Visualizações
Show structure after payment Auto-renewable subscriptions (SwiftUI)

I have a code for auto-renewable subscriptions, how to close the subscription window after paying for the subscription and display the ContentView() structure.

import Foundation
import StoreKit

typealias FetchCompletionHandler = (([SKProduct]) -> Void)
typealias PurchaseCompletionHandler = ((SKPaymentTransaction?) -> Void)

class Store: NSObject, ObservableObject {
    
   @Published var allRecipes = [Recipe]()
    
    private let allProductIdentifiers = Set([
    "PRODUCT_ID_APP_STORE_CONNECT"])
    
    private var completedPurchases = [String]() {
        didSet {
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                for index in self.allRecipes.indices {
                    self.allRecipes[index].isLocked = !self.completedPurchases.contains(self.allRecipes[index].id)
                }
            }
        }
    }
    
    private var productsRequest: SKProductsRequest?
    private var fetchedProducts = [SKProduct]()
    private var fetchCompletionHandler: FetchCompletionHandler?
    private var purchaseCompletionHandler: PurchaseCompletionHandler?
    
    private let userDefaultsKey = "PRODUCT_ID_APP_STORE_CONNECT"
    
    override init() {
        super.init()
        
        startObservingPaymentQueue()
        
        fetchProducts { products in
            self.allRecipes = products.map { Recipe(product: $0) }
        }
    }
    
    func loadStorePurchases() {
        if let storePurchases = UserDefaults.standard.object(forKey: userDefaultsKey) as? [String] {
            self.completedPurchases = storePurchases
        }
    }
    
    private func startObservingPaymentQueue() {
        SKPaymentQueue.default().add(self)
    }
    
    private func fetchProducts(_ completion: @escaping FetchCompletionHandler) {
        guard self.productsRequest == nil else { return }
        
        fetchCompletionHandler = completion
        
        productsRequest = SKProductsRequest(productIdentifiers: allProductIdentifiers)
        productsRequest?.delegate = self
        productsRequest?.start()
        
    }
    
    private func buy(_ product: SKProduct, completion: @escaping PurchaseCompletionHandler) {
        purchaseCompletionHandler = completion
        
        let payment = SKPayment(product: product)
        SKPaymentQueue.default().add(payment)
    }
}

extension Store {
    
    func product(for identifier: String) -> SKProduct? {
        return fetchedProducts.first(where: { $0.productIdentifier == identifier })
    }
    
    func purchaseProduct(_ product: SKProduct) {
        startObservingPaymentQueue()
        buy(product) { _ in }
    }
    

    func restorePurchases() {
        SKPaymentQueue.default().restoreCompletedTransactions()
    }
}

extension Store: SKPaymentTransactionObserver {
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        for transaction in transactions {
            var shouldFinishTransaction = false
            switch transaction.transactionState {
                

            case .purchased, .restored:
                completedPurchases.append(transaction.payment.productIdentifier)
                shouldFinishTransaction = true
            case .failed:
                shouldFinishTransaction = true
            case .deferred, .purchasing:
                break
            @unknown default:
                break
            }
            
            if shouldFinishTransaction {
                SKPaymentQueue.default().finishTransaction(transaction)
                DispatchQueue.main.async {
                    self.purchaseCompletionHandler?(transaction)
                    self.purchaseCompletionHandler = nil
                }
            }
        }
        
        if !completedPurchases.isEmpty {
            UserDefaults.standard.setValue(completedPurchases, forKey: userDefaultsKey)
        }
    }
    
    
}

extension Store: SKProductsRequestDelegate {
    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        let loadedProducts = response.products
        let invalidProducts = response.invalidProductIdentifiers
        
        guard !loadedProducts.isEmpty else {
            print("Cloud not load the products!")
            if !invalidProducts.isEmpty {
                print("Invalid Products found: \(invalidProducts)")
            }
            productsRequest = nil 
            return
        }
        
        // Cache the fetched products
        fetchedProducts = loadedProducts
        // Notifi anyone waiting on the product load
        DispatchQueue.main.async {
            self.fetchCompletionHandler?(loadedProducts)
            
            self.fetchCompletionHandler = nil
            self.productsRequest = nil
        }
    }
    
    
}

structure Recipe()

import Foundation
import StoreKit


struct Recipe: Hashable {
    let id: String
    let title: String
    let description: String
    var isLocked: Bool
    var price: String?
    let locale: Locale
    let imageName: String
    
    lazy var formatter: NumberFormatter = {
       let nf = NumberFormatter()
        nf.numberStyle = .currency
        nf.locale = locale
        return nf
        
    }()
    
    init(product: SKProduct, isLocked: Bool = true) {
        self.id = product.productIdentifier
        self.title = product.localizedTitle
        self.description = product.localizedDescription
        self.isLocked = isLocked
        self.locale = product.priceLocale
        self.imageName = product.productIdentifier
        
        if isLocked {
            self.price = formatter.string(from: product.price)
        }
    }
}

this is my structure with subscribe display and subscribe button

import SwiftUI
import Foundation
import StoreKit


struct Te: View {
    
    @ObservedObject var store = Store()

    var body: some View {
        
        ZStack {
            
            // After paying for the subscription, the subscription window disappears and the ContentViev() structure appears
            ContentView()
            
            VStack {
                ZStack(alignment: .center) {
                    Image("subs")
                        .resizable()
                        .overlay(Color.black.opacity(0.6))
                        .frame(height: 600)
                        .blur(radius: 15)
                        .padding(.top)
                    
                    
                    VStack {
                        
                        Text("ALL ACCESS")
                            .font(.system(size: 32))
                            .fontWeight(.bold)
                            .foregroundColor(.white)
                            .multilineTextAlignment(.center)
                            .padding(.bottom, 1)
                        
                        Text("UNLOCK ALL ACCESS")
                            .foregroundColor(.white)
                            .font(.system(size: 14))
                            .multilineTextAlignment(.center)
                            .padding(.horizontal,35)
                        
                        
                        VStack(alignment: .leading) {
                            
                            HStack {
                                
                                Image(systemName: "checkmark.seal")
                                    .resizable()
                                    .scaledToFit()
                                    .frame(width: 25, height: 25)
                                    .foregroundColor(.white)
                                Text("Ads")
                                    .foregroundColor(.white)
                            }
                            
                            HStack {
                                
                                Image(systemName: "checkmark.seal")
                                    .resizable()
                                    .scaledToFit()
                                    .frame(width: 25, height: 25)
                                    .foregroundColor(.white)
                                Text("Item")
                                    .foregroundColor(.white)
                            }
                            
                            HStack {
                                
                                Image(systemName: "checkmark.seal")
                                    .resizable()
                                    .scaledToFit()
                                    .frame(width: 25, height: 25)
                                    .foregroundColor(.white)
                                Text("New")
                                    .foregroundColor(.white)
                                
                            }
                            
                        }.padding(.top, 50)
                        
                        
                        Button(action: {
                            store.purchaseProduct(store.product(for: "PRODUCT_ID_APP_STORE_CONNECT")!)
                            
                        }, label: {
                            Text("SUBSCRIBE")
                                .fontWeight(.bold)
                                .padding()
                                .padding(.horizontal,45)
                                .background(Color.blue.opacity(0.5))
                                .foregroundColor(Color.white)
                                .cornerRadius(10)
                        })
                            .padding(.top,45)
                            .padding(.bottom, 25)
                        
                    }.padding(.top,5)
                    
                }
                
            }
            
        }
        
    }
}

After paying for the subscription, the subscription window should disappear and the ContentView () structure will be displayed in its place, if you know about auto-renewable subscriptions, please look at my code, maybe I made a mistake somewhere. Thanks for any help

over 4 years ago · Santiago Trujillo
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda