Browse Source

Moved logic to retrieve products info to ProductsInfoController

Andrea Bizzotto 8 năm trước cách đây
mục cha
commit
439dc61ed5

+ 8 - 0
SwiftyStoreKit.xcodeproj/project.pbxproj

@@ -24,6 +24,9 @@
 		650307F81E317BCF001332A4 /* CompleteTransactionsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 650307F71E317BCF001332A4 /* CompleteTransactionsController.swift */; };
 		650307F91E317BCF001332A4 /* CompleteTransactionsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 650307F71E317BCF001332A4 /* CompleteTransactionsController.swift */; };
 		650307FA1E317BCF001332A4 /* CompleteTransactionsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 650307F71E317BCF001332A4 /* CompleteTransactionsController.swift */; };
+		650307FC1E33154F001332A4 /* ProductsInfoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 650307FB1E33154F001332A4 /* ProductsInfoController.swift */; };
+		650307FD1E33154F001332A4 /* ProductsInfoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 650307FB1E33154F001332A4 /* ProductsInfoController.swift */; };
+		650307FE1E33154F001332A4 /* ProductsInfoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 650307FB1E33154F001332A4 /* ProductsInfoController.swift */; };
 		653722811DB8282600C8F944 /* SKProduct+LocalizedPrice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653722801DB8282600C8F944 /* SKProduct+LocalizedPrice.swift */; };
 		653722821DB8290A00C8F944 /* SKProduct+LocalizedPrice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653722801DB8282600C8F944 /* SKProduct+LocalizedPrice.swift */; };
 		653722831DB8290B00C8F944 /* SKProduct+LocalizedPrice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653722801DB8282600C8F944 /* SKProduct+LocalizedPrice.swift */; };
@@ -137,6 +140,7 @@
 		650307F11E3163AA001332A4 /* RestorePurchasesControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestorePurchasesControllerTests.swift; sourceTree = "<group>"; };
 		650307F31E3177EF001332A4 /* RestorePurchasesController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestorePurchasesController.swift; sourceTree = "<group>"; };
 		650307F71E317BCF001332A4 /* CompleteTransactionsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompleteTransactionsController.swift; sourceTree = "<group>"; };
+		650307FB1E33154F001332A4 /* ProductsInfoController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProductsInfoController.swift; sourceTree = "<group>"; };
 		653722801DB8282600C8F944 /* SKProduct+LocalizedPrice.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SKProduct+LocalizedPrice.swift"; sourceTree = "<group>"; };
 		658A08361E2EC24E0074A98F /* PaymentQueueController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaymentQueueController.swift; sourceTree = "<group>"; };
 		658A083E1E2EC5120074A98F /* SwiftyStoreKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftyStoreKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -253,6 +257,7 @@
 			children = (
 				6502F6241B98586A004E342D /* SwiftyStoreKit.swift */,
 				65BB6CE71DDB018900218A0B /* SwiftyStoreKit+Types.swift */,
+				650307FB1E33154F001332A4 /* ProductsInfoController.swift */,
 				6502F6231B98586A004E342D /* InAppProductQueryRequest.swift */,
 				658A08361E2EC24E0074A98F /* PaymentQueueController.swift */,
 				65F70AC81E2EDC3700BF040D /* PaymentsController.swift */,
@@ -584,6 +589,7 @@
 				54B069961CF744DC00BAFE38 /* OS.swift in Sources */,
 				54B069931CF742D300BAFE38 /* InAppReceiptRefreshRequest.swift in Sources */,
 				65F70ACB1E2EDC3700BF040D /* PaymentsController.swift in Sources */,
+				650307FE1E33154F001332A4 /* ProductsInfoController.swift in Sources */,
 				650307F61E3177EF001332A4 /* RestorePurchasesController.swift in Sources */,
 				658A08391E2EC24E0074A98F /* PaymentQueueController.swift in Sources */,
 				653722831DB8290B00C8F944 /* SKProduct+LocalizedPrice.swift in Sources */,
@@ -613,6 +619,7 @@
 				6502F63B1B985CA1004E342D /* InAppProductQueryRequest.swift in Sources */,
 				C4083C571C2AB0A900295248 /* InAppReceiptRefreshRequest.swift in Sources */,
 				65F70AC91E2EDC3700BF040D /* PaymentsController.swift in Sources */,
+				650307FC1E33154F001332A4 /* ProductsInfoController.swift in Sources */,
 				650307F41E3177EF001332A4 /* RestorePurchasesController.swift in Sources */,
 				658A08371E2EC24E0074A98F /* PaymentQueueController.swift in Sources */,
 				653722811DB8282600C8F944 /* SKProduct+LocalizedPrice.swift in Sources */,
@@ -647,6 +654,7 @@
 				C4D74BC41C24CEDC0071AD3E /* InAppProductQueryRequest.swift in Sources */,
 				C4F69A8A1C2E0D21009DD8BD /* InAppReceiptRefreshRequest.swift in Sources */,
 				65F70ACA1E2EDC3700BF040D /* PaymentsController.swift in Sources */,
+				650307FD1E33154F001332A4 /* ProductsInfoController.swift in Sources */,
 				650307F51E3177EF001332A4 /* RestorePurchasesController.swift in Sources */,
 				658A08381E2EC24E0074A98F /* PaymentQueueController.swift in Sources */,
 				653722821DB8290A00C8F944 /* SKProduct+LocalizedPrice.swift in Sources */,

+ 77 - 0
SwiftyStoreKit/ProductsInfoController.swift

@@ -0,0 +1,77 @@
+//
+// ProductsInfoController.swift
+// SwiftyStoreKit
+//
+// Copyright (c) 2015 Andrea Bizzotto (bizz84@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+import StoreKit
+
+class ProductsInfoController: NSObject {
+
+    // MARK: Private declarations
+
+    // As we can have multiple inflight queries and purchases, we store them in a dictionary by product id
+    private var inflightQueries: [Set<String>: InAppProductQueryRequest] = [:]
+
+    private(set) var products: [String: SKProduct] = [:]
+
+    private func addProduct(_ product: SKProduct) {
+        products[product.productIdentifier] = product
+    }
+    
+    private func allProductsMatching(_ productIds: Set<String>) -> Set<SKProduct>? {
+        
+        var requestedProducts = Set<SKProduct>()
+        
+        for productId in productIds {
+            
+            guard let product = products[productId] else {
+                return nil
+            }
+            requestedProducts.insert(product)
+        }
+        return requestedProducts
+    }
+    
+    private func requestProducts(_ productIds: Set<String>, completion: @escaping (RetrieveResults) -> ()) {
+        
+        inflightQueries[productIds] = InAppProductQueryRequest.startQuery(productIds) { result in
+            
+            self.inflightQueries[productIds] = nil
+            for product in result.retrievedProducts {
+                self.addProduct(product)
+            }
+            completion(result)
+        }
+    }
+    
+    func retrieveProductsInfo(_ productIds: Set<String>, completion: @escaping (RetrieveResults) -> ()) {
+        
+        guard let products = allProductsMatching(productIds) else {
+            
+            requestProducts(productIds, completion: completion)
+            return
+        }
+        completion(RetrieveResults(retrievedProducts: products, invalidProductIDs: [], error: nil))
+    }
+
+}

+ 13 - 47
SwiftyStoreKit/SwiftyStoreKit.swift

@@ -26,28 +26,9 @@ import StoreKit
 
 public class SwiftyStoreKit {
 
-    // MARK: Private declarations
-    private class InAppPurchaseStore {
-        var products: [String: SKProduct] = [:]
-        func addProduct(_ product: SKProduct) {
-            products[product.productIdentifier] = product
-        }
-        func allProductsMatching(_ productIds: Set<String>) -> Set<SKProduct>? {
-            var requestedProducts = Set<SKProduct>()
-            for productId in productIds {
-                guard let product = products[productId] else {
-                    return nil
-                }
-                requestedProducts.insert(product)
-            }
-            return requestedProducts
-        }
-    }
-    private var store: InAppPurchaseStore = InAppPurchaseStore()
+    private let productsInfoController = ProductsInfoController()
 
-    // As we can have multiple inflight queries and purchases, we store them in a dictionary by product id
-    private var inflightQueries: [Set<String>: InAppProductQueryRequest] = [:]
-    private var paymentQueueController = PaymentQueueController(paymentQueue: SKPaymentQueue.default())
+    private let paymentQueueController = PaymentQueueController(paymentQueue: SKPaymentQueue.default())
     
     private var receiptRefreshRequest: InAppReceiptRefreshRequest?
     
@@ -63,21 +44,10 @@ public class SwiftyStoreKit {
         return SKPaymentQueue.canMakePayments()
     }
 
-    
-    public class func completeTransactions(atomically: Bool = true, completion: @escaping ([Product]) -> ()) {
-        
-        sharedInstance.paymentQueueController.completeTransactions(CompleteTransactions(atomically: atomically, callback: completion))
-    }
-    
-    // MARK: Public methods
+    // MARK: Public methods - Purchases
     public class func retrieveProductsInfo(_ productIds: Set<String>, completion: @escaping (RetrieveResults) -> ()) {
         
-        guard let products = sharedInstance.store.allProductsMatching(productIds) else {
-            
-            sharedInstance.requestProducts(productIds, completion: completion)
-            return
-        }
-        completion(RetrieveResults(retrievedProducts: products, invalidProductIDs: [], error: nil))
+        return sharedInstance.productsInfoController.retrieveProductsInfo(productIds, completion: completion)
     }
     
     /**
@@ -89,7 +59,7 @@ public class SwiftyStoreKit {
      */
     public class func purchaseProduct(_ productId: String, atomically: Bool = true, applicationUsername: String = "", completion: @escaping ( PurchaseResult) -> ()) {
         
-        if let product = sharedInstance.store.products[productId] {
+        if let product = sharedInstance.productsInfoController.products[productId] {
             sharedInstance.purchase(product: product, atomically: atomically, applicationUsername: applicationUsername, completion: completion)
         }
         else {
@@ -116,11 +86,19 @@ public class SwiftyStoreKit {
         })
     }
     
+    public class func completeTransactions(atomically: Bool = true, completion: @escaping ([Product]) -> ()) {
+        
+        sharedInstance.paymentQueueController.completeTransactions(CompleteTransactions(atomically: atomically, callback: completion))
+    }
+    
+
     public class func finishTransaction(_ transaction: PaymentTransaction) {
      
         sharedInstance.paymentQueueController.finishTransaction(transaction)
     }
 
+    // MARK: Public methods - Receipt verification
+
     /**
      * Return receipt data from the application bundle. This is read from Bundle.main.appStoreReceiptURL
      */
@@ -237,18 +215,6 @@ public class SwiftyStoreKit {
         return RestoreResults(restoredProducts: restoredProducts, restoreFailedProducts: restoreFailedProducts)
     }
     
-    private func requestProducts(_ productIds: Set<String>, completion: @escaping (RetrieveResults) -> ()) {
-        
-        inflightQueries[productIds] = InAppProductQueryRequest.startQuery(productIds) { result in
-        
-            self.inflightQueries[productIds] = nil
-            for product in result.retrievedProducts {
-                self.store.addProduct(product)
-            }
-            completion(result)
-        }
-    }
-    
     private func storeInternalError(code: Int = 0, description: String = "") -> NSError {
         return NSError(domain: "SwiftyStoreKit", code: code, userInfo: [ NSLocalizedDescriptionKey: description ])
     }