I created a package library to manage InAppPurchase. I don't know if my approach is correct
Before that, normally I used the file copied from project to project. I've a doubt when I'd like to use something like enum to quickly identify the product purchased.
For example, before the package, my product was inside an Enum:
public struct InApp {
enum ProductType: String, CaseIterable {
case unlockSection1 = "it.site.AppName.unlockSection1"
case unlockSection2 = "it.site.AppName.unlockSection2"
case unlockSection3 = "it.site.AppName.unlockSection3"
static let allValues = ProductType.allCases.map { $0.rawValue }
}
}
Class to manage product (only some func):
class IAPSwiftUIModel: NSObject, ObservableObject, SKProductsRequestDelegate, SKPaymentTransactionObserver {
@Published var allProducts = [SKProduct]()
@Published var purchasedProductIdentifiers: Set<String> = []
override init() {
super.init()
fetchAvailableProducts()
isPurchaseDisabled = canMakePurchases()
}
func isProductPurchased(product: InApp.ProductType) -> Bool {
return purchasedProductIdentifiers.contains(product.rawValue)
}
func fetchAvailableProducts() {
let productIdentifiers = Set(InApp.ProductType.allValues)
print(productIdentifiers)
productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers)
productsRequest.delegate = self
productsRequest.start()
}
}
Now, with Package, I can't use an enum to identify the product, so I created a Plist with all the identifiers:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<string>it.site.AppName.unlockSection1</string>
<string>it.site.AppName.unlockSection2</string>
<string>it.site.AppName.unlockSection3</string>
</array>
</plist>
IN PACKAGE
///get productsIdentifiers from plist "InAppProducts.plist"
public class IAPProducts {
public static var sharedInstance = IAPProducts()
init() {
productsIdentifiers = getProductsFromPlist()
}
public var productsIdentifiers: [String] = []
private func getProductsFromPlist() -> [String] {
if let url = Bundle.main.url(forResource:"InAppProducts", withExtension: "plist") {
do {
let data = try Data(contentsOf:url)
if let swiftDictionary = try PropertyListSerialization.propertyList(from: data, format: nil) as? [String] {
return swiftDictionary
}
}
catch {
print("getDicFromPlist: (error.localizedDescription)")
return []
}
}
fatalError("no found InAppProducts.plist")
}
}
Changing the fetch inside IAPSwiftModel
public func fetchAvailableProducts() {
let allProduct = IAPProducts.sharedInstance.productsIdentifiers **//this line**
let productIdentifiers = Set(allProduct)
print(productIdentifiers)
productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers)
productsRequest.delegate = self
productsRequest.start()
}
INSIDE THE APP
**/// This to substitute the enum ProductType**
/// I can't use an enum dynamically
struct AppProductsIdentifiers {
static let unlockSection1 = IAPProducts.sharedInstance.productsIdentifiers[0]
static let unlockSection2 = IAPProducts.sharedInstance.productsIdentifiers[1]
static let unlockSection3 = IAPProducts.sharedInstance.productsIdentifiers[2]
}
public struct IAPViewTest: View {
public var inAppModel = IAPSwiftUIModel()
public init() {}
public var body: some View {
VStack {
/// All products from apple fetch
List(inAppModel.allProducts, id:.self) { product in
Text(product.localizedTitle)
}
/// All productIdentifiers from plist
Text("lista nomi da plist")
List(IAPProducts.sharedInstance.productsIdentifiers, id:.self) { product in
Text(product)
}
Text(inAppModel.isProductPurchased(productIdentifier: AppProductsIdentifiers. unlockSection1) ? "Section1 purchased" : "Section1 blocked")
Text(inAppModel.isProductPurchased(productIdentifier: AppProductsIdentifiers. unlockSection1) ? "Section2 purchased" : "Section2 blocked")
Text(inAppModel.isProductPurchased(productIdentifier: AppProductsIdentifiers. unlockSection1) ? "Section3 purchased" : "Section3 blocked")
}
}
}
struct IAPViewApp_Previews: PreviewProvider {
static var previews: some View {
IAPViewTest()
}
}
question from:
https://stackoverflow.com/questions/65869788/inapp-purchase-manage-product-type-coming-from-plist-inside-package-library