2017-01-27 4 views
-2

인앱 구매를 통합하려고합니다. 웬일인지 나는 '치명적인 오류 : 인덱스가 범위를 벗어남'이라는 SKProduct 제품을 보유하고있는 배열로 치명적인 오류가 발생했습니다. 나는 앱 구매에서 하나의 소모품을 가지고 있지만 나중에 더 추가하기로 결정할 수 있습니다. 구매할 수 있도록 PREMIUM_PRODUCT_ID 제품에 액세스하려고합니다. 이 오류는 purchaseMyProduct 함수가 호출 될 때 발생합니다. iapProducts 배열이 범위를 벗어나는 이유는 무엇입니까? 당신의 도움을 주셔서 감사합니다!
치명적인 오류가이 라인에서 발생 purchaseMyProduct(product: iapProducts[0])배열이 범위를 벗어나는 이유는 무엇입니까?

import UIKit 
import StoreKit 


class Settings: UIViewController, SKProductsRequestDelegate, 
SKPaymentTransactionObserver { 

    let PREMIUM_PRODUCT_ID = "---------------" 

    var productID = "" 
    var productsRequest = SKProductsRequest() 
    var iapProducts = [SKProduct]() 
    var nonConsumablePurchaseMade = UserDefaults.standard.bool(forKey: "nonConsumablePurchaseMade") 



    @IBOutlet weak var adsBtn: UIButton! 
    @IBAction func restorePurchase(_ sender: Any) { 
     SKPaymentQueue.default().add(self) 
     SKPaymentQueue.default().restoreCompletedTransactions() 

     // Check your In-App Purchases 
     print("NON CONSUMABLE PURCHASE MADE: \(nonConsumablePurchaseMade)") 


     // Fetch IAP Products available 
     fetchAvailableProducts() 

     UIAlertView(title: "IAP Tutorial", 
        message: "You've successfully restored your purchase!", 
        delegate: nil, cancelButtonTitle: "OK").show() 
    } 

    @IBAction func review(_ sender: Any) { 
     UIApplication.shared.openURL(NSURL(string: "-----------------")! as URL) 

    } 


    @IBAction func removeAds(_ sender: Any) { 
     //UIApplication.shared.openURL(NSURL(string: "----------------")! as URL) 

     purchaseMyProduct(product: iapProducts[0]) 

    } 


    override func viewDidLoad() { 
     super.viewDidLoad() 


     // Do any additional setup after loading the view. 


    } 

    ... 

    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) { 
     nonConsumablePurchaseMade = true 
     UserDefaults.standard.set(nonConsumablePurchaseMade, forKey: "nonConsumablePurchaseMade") 

     /*UIAlertView(title: "IAP Tutorial", 
        message: "You've successfully restored your purchase!", 
        delegate: nil, cancelButtonTitle: "OK").show()*/ 
    } 

    func fetchAvailableProducts() { 

     // Put here your IAP Products ID's 
     let productIdentifiers = NSSet(objects: 
             PREMIUM_PRODUCT_ID 
     ) 

     productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers as! Set<String>) 
     productsRequest.delegate = self 
     productsRequest.start() 
    } 

    func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) { 
     if (response.products.count > 0) { 
      iapProducts = response.products 

      // 1st IAP Product (Consumable) ------------------------------------ 
      let firstProduct = response.products[0] as SKProduct 

      // Get its price from iTunes Connect 
      let numberFormatter = NumberFormatter() 
      numberFormatter.formatterBehavior = .behavior10_4 
      numberFormatter.numberStyle = .currency 
      numberFormatter.locale = firstProduct.priceLocale 
      let price1Str = numberFormatter.string(from: firstProduct.price) 

      // Show its description 
      //consumableLabel.text = firstProduct.localizedDescription + "\nfor just \(price1Str!)" 
      // ------------------------------------------------ 



      // 2nd IAP Product (Non-Consumable) ------------------------------ 
      let secondProd = response.products[0] as SKProduct 

      // Get its price from iTunes Connect 
      numberFormatter.locale = secondProd.priceLocale 
      let price2Str = numberFormatter.string(from: secondProd.price) 

      // Show its description 
      //nonConsumableLabel.text = secondProd.localizedDescription + "\nfor just \(price2Str!)" 
      // ------------------------------------ 
     } 
    } 

    func canMakePurchases() -> Bool { return SKPaymentQueue.canMakePayments() } 
    func purchaseMyProduct(product: SKProduct) { 
     if self.canMakePurchases() { 
      let payment = SKPayment(product: product) 
      SKPaymentQueue.default().add(self) 
      SKPaymentQueue.default().add(payment) 

      print("PRODUCT TO PURCHASE: \(product.productIdentifier)") 
      productID = product.productIdentifier 


      // IAP Purchases dsabled on the Device 
     } else { 
      UIAlertView(title: "IAP Tutorial", 
         message: "Purchases are disabled in your device!", 
         delegate: nil, cancelButtonTitle: "OK").show() 
     } 
    } 

    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { 
     for transaction:AnyObject in transactions { 
      if let trans = transaction as? SKPaymentTransaction { 
       switch trans.transactionState { 

       case .purchased: 
        SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction) 

        // The Consumable product (10 coins) has been purchased -> gain 10 extra coins! 
        if productID == PREMIUM_PRODUCT_ID { 

         // Save your purchase locally (needed only for Non-Consumable IAP) 
         nonConsumablePurchaseMade = true 
         UserDefaults.standard.set(nonConsumablePurchaseMade, forKey: "nonConsumablePurchaseMade") 

         //premiumLabel.text = "Premium version PURCHASED!" 

         UIAlertView(title: "IAP Tutorial", 
            message: "You've successfully unlocked the Premium version!", 
            delegate: nil, 
            cancelButtonTitle: "OK").show() 
        } 

        break 

       case .failed: 
        SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction) 
        break 
       case .restored: 
        SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction) 
        break 

       default: break 
       }}} 
    } 

} 
+0

오류는 배열의 존재하지 않는 요소 (예 : 3 개 항목의 배열의 네 번째 항목)에 액세스하려고한다는 것을 의미합니다. 오류가 발생한 줄은 무엇입니까? – Coder256

+0

두 가지 방법으로 질문을 편집하십시오. (1) 문제와 관련이없는 코드는 제거하십시오.이 코드를 모두 따라갈 수는 없습니다. (2) 오류를 줄 수있는 코드 줄을 정확히 가리 킵니다. (당신은 분명할지 모르겠지만 코드를 얼마나 많이 제공했는지는 알기가 정말 어렵습니다. 보너스 : 코드에 중단 점을 설정 했습니까? 어떤 배열인지 알 수있는 곳과 내용은 오류가 발생했을 때입니까? – dfd

+0

ok 업데이트 할 것입니다. –

답변

0

귀하의 코드가 너무 길고, 그래서 관련 무엇인지 추측 내가 교육을 만들기의 자유를했다 :

import UIKit 
import StoreKit 

class Settings: UIViewController, SKProductsRequestDelegate, 
SKPaymentTransactionObserver { 

    var iapProducts = [SKProduct]() 

    @IBAction func removeAds(_ sender: Any) { 
     purchaseMyProduct(product: iapProducts[0]) 

    } 
} 

당신이 iapProducts를 선언 할 때, 값이없는 빈 배열을 만드는 중입니다.

그런 다음 removeAds 함수에서 첫 번째 요소로 무엇인가를 수행한다고 말합니다.

나는 아무것도 존재하지 않는다는 사실을 추측 할 것이므로, 존재하지 않는 개체에 액세스하도록 강요합니다.

다음을 시도하여 문제가 해결되는지 확인하십시오.

  1. 그것은 선택
  2. 가드 문 안전하게 첫 번째 제품을 펼쳤다 당신의 [SKProduct] 배열을 만들고, 하나가 존재하는 경우에만 수정, 그것은 당신의 purchaseMyProduct를 호출하려고합니다 :
    var iapProducts: [SKProduct]? 
    
    @IBAction func removeAds(_ sender: Any) { 
        guard let product = iapProducts?.first else { return } 
    
        purchaseMyProduct(product: product) 
    } 
    

    두 가지를 달성 기능. 그렇지 않으면 그냥 종료됩니다.
관련 문제