         }
     }
     
-    private func callPurchaseProductCompletionForProduct(productId: String, error: NSError?) {
-        dispatch_async(dispatch_get_main_queue()) {
+    fileprivate func callPurchaseProductCompletion(productId: String, error: Error?) {
+        DispatchQueue.main.async {
             for i in 0..<self.purchaseProductRequests.count {
                 let requestInfo = self.purchaseProductRequests[i]
                 if requestInfo.productId == productId {
-                    self.purchaseProductRequests.removeAtIndex(i)
+                    self.purchaseProductRequests.remove(at: i)
                     requestInfo.completion(error)
                     return
                 }

        request.start()
    }
    
    public func purchaseProductWithId(productId: String, completion: PurchaseProductCompletionBlock) {
        if !canMakePayments() {
            let error = NSError(domain: "inapppurchase", code: 0, userInfo: [NSLocalizedDescriptionKey: "In App Purchasing is unavailable"])
            completion(error)
        } else {
            loadProductsWithIds([productId]) { (products, error) -> Void in
                if error != nil {
                    completion(error)
                } else {
                    if let product = products?.first {
                        self.purchaseProduct(product, completion: completion)
                    }
                }
            }
        }
    }
    
    public func purchaseProduct(product: SKProduct, completion: PurchaseProductCompletionBlock) {
        purchaseProductRequests.append(PurchaseProductRequestInfo(productId: product.productIdentifier, completion: completion))
        let payment = SKPayment(product: product)
        SKPaymentQueue.defaultQueue().addPayment(payment)
    }
    
    private func callLoadProductsCompletionForRequest(request: SKProductsRequest, responseProducts:Array<SKProduct>?, error: NSError?) {
        dispatch_async(dispatch_get_main_queue()) {
            for i in 0..<self.loadProductsRequests.count {
                let requestInfo = self.loadProductsRequests[i]
                if requestInfo.request == request {
                    self.loadProductsRequests.removeAtIndex(i)
                    requestInfo.completion(responseProducts, error)
                    return
                }

import Foundation
import StoreKit

public typealias RestoreTransactionsCompletionBlock = (Error?) -> Void
public typealias LoadProductsCompletionBlock = (Array<SKProduct>?, Error?) -> Void
public typealias PurchaseProductCompletionBlock = (Error?) -> Void
public typealias LoadProductsRequestInfo = (request: SKProductsRequest, completion: LoadProductsCompletionBlock)
public typealias PurchaseProductRequestInfo = (productId: String, completion: PurchaseProductCompletionBlock)

public class IAPManager: NSObject {
    public static let shared = IAPManager()
    
    override init() {
        super.init()
        
        restorePurchasedItems()
        
        SKPaymentQueue.default().add(self)
        
        NotificationCenter.default.addObserver(self, selector: #selector(IAPManager.savePurchasedItems), name: NSNotification.Name.UIApplicationDidEnterBackground, object: nil)
    }
    
    public func canMakePayments() -> Bool {
