2013-10-19 49 views
-2

我最近向App Store提交了一個應用程序。客戶在嘗試購買應用程序內購買(或任何相關事宜)時報告了崩潰;但不幸的是,我無法在開發版本中複製它。這裏是崩潰日誌:App Store崩潰但未開發

https://www.dropbox.com/s/ml9xvb1pk7hxtiu/memejump.crash 

使用xcode 5.是否有可能是編譯器的問題?

編輯:

是所有單邊行動計劃提交我想我知道爲什麼崩潰就在這裏。我有一系列巨大的,複雜的,不可靠的if語句來檢查請求是爲購買做出的,還是僅僅爲了獲得價格,以便不彈出警報視圖。一定有什麼問題,但我找不到它......有沒有人知道一種方法來檢查它是一種購買還是隻是一個要求顯示價格的請求?我將很快用符號化的崩潰冒充代碼。

#import "StoreViewController.h" 

int internetActive; 

BOOL forButtonsAndLabels; 
BOOL forPurchase; 
BOOL fakePurchase; 

@interface StoreViewController() 

@end 

@implementation StoreViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    //for internet test 
    // check for internet connection 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil]; 

    internetReachable = [Reachability reachabilityForInternetConnection]; 
    [internetReachable startNotifier]; 

    // check if a pathway to a random host exists 
    hostReachable = [Reachability reachabilityWithHostName: @"www.apple.com"]; 
    [hostReachable startNotifier]; 

} 


- (void)setButtonsAndLabelsForExtraCoins { 

    if (internetActive == YES) { 

     forButtonsAndLabels = YES; 

     SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObjects:@"com.ge0rges.Meme_Jump.4000C",@"com.ge0rges.Meme_Jump.9000C", @"com.ge0rges.Meme_Jump.24000C", nil]]; 

     request.delegate = self; 
     [request start]; 

     [activityindicatorButton24000 startAnimating]; 
     [activityindicatorButton4000 startAnimating]; 
     [activityindicatorButton9000 startAnimating]; 

     activityindicatorButton24000.hidden = NO; 
     activityindicatorButton4000.hidden = NO; 
     activityindicatorButton9000.hidden = NO; 

     CoinsButton4000.hidden = YES; 
     CoinsButton9000.hidden = YES; 
     CoinsButton24000.hidden = YES; 

    } else { 

     [CoinsButton4000 setTitle:NSLocalizedString(@"N/A", nil) forState:UIControlStateNormal]; 
     [CoinsButton9000 setTitle:NSLocalizedString(@"N/A", nil) forState:UIControlStateNormal]; 
     [CoinsButton24000 setTitle:NSLocalizedString(@"N/A", nil) forState:UIControlStateNormal]; 

     [CoinsLabel4000 setText:nil]; 
     [CoinsLabel9000 setText:nil]; 
     [CoinsLabel24000 setText:nil]; 

     CoinsButton4000.hidden = NO; 
     CoinsButton9000.hidden = NO; 
     CoinsButton24000.hidden = NO; 

     [activityindicatorButton24000 stopAnimating]; 
     [activityindicatorButton4000 stopAnimating]; 
     [activityindicatorButton9000 stopAnimating]; 

     forButtonsAndLabels = YES; 
     forPurchase = NO; 
    } 
} 

#pragma mark - checking internet 
- (void)checkNetworkStatus:(NSNotification *)notice 
{ 
    // called after network status changes 
    NetworkStatus internetStatus = [internetReachable currentReachabilityStatus]; 
    switch (internetStatus) 
    { 
     case NotReachable: 
     { 
      internetActive = NO; 
      forPurchase = NO; 
      forButtonsAndLabels = YES; 

      [self setButtonsAndLabelsForExtraCoins]; 

      break; 
     } 
     case ReachableViaWiFi: 
     { 
      internetActive = YES; 

      [self setButtonsAndLabelsForExtraCoins]; 

      break; 
     } 
     case ReachableViaWWAN: 
     { 
      internetActive = YES; 

      [self setButtonsAndLabelsForExtraCoins]; 

      break; 
     } 
    } 
} 

#pragma mark - buying extra coins 

- (IBAction)buy4000Coins { 

    CoinsButton4000.hidden = YES; 

    [activityindicatorButton4000 startAnimating]; 
    activityindicatorButton4000.hidden = NO; 

    if (internetActive == NO) { 

     CoinsButton4000.hidden = NO; 
     [activityindicatorButton4000 stopAnimating]; 

     UIAlertView *nointernet = [[UIAlertView alloc] 
            initWithTitle: NSLocalizedString(@"No internet connection", nil) 
            message: NSLocalizedString(@"It seems you are not connected to the internet. in-app purchases require a internet connection. Please connect to the internet and try again.", nil) 
         delegate:nil 
         cancelButtonTitle:@"OK" 
         otherButtonTitles:nil, nil]; 


     [nointernet show]; 

    } else { 

     identifier = @"com.ge0rges.Meme_Jump.4000C"; 
     [self checkForParentPermission]; 

    } 
} 

- (IBAction)buy9000Coins { 

    CoinsButton9000.hidden = YES; 

    [activityindicatorButton9000 startAnimating]; 
    activityindicatorButton9000.hidden = NO; 

    if (internetActive == NO) { 

     CoinsButton9000.hidden = NO; 
     [activityindicatorButton9000 stopAnimating]; 

     UIAlertView *nointernet = [[UIAlertView alloc] 
            initWithTitle: NSLocalizedString(@"No internet connection", nil) 
            message: NSLocalizedString(@"It seems you are not connected to the internet. in-app purchases require a internet connection. Please connect to the internet and try again.", nil) 
            delegate:nil 
            cancelButtonTitle:@"OK" 
            otherButtonTitles:nil, nil]; 


     [nointernet show]; 

    } else { 

     identifier = @"com.ge0rges.Meme_Jump.9000C"; 
     [self checkForParentPermission]; 

    } 
} 

- (IBAction)buy24000Coins { 

    CoinsButton24000.hidden = YES; 

    [activityindicatorButton24000 startAnimating]; 
    activityindicatorButton24000.hidden = NO; 

    if (internetActive == NO) { 

     CoinsButton24000.hidden = NO; 
     [activityindicatorButton24000 stopAnimating]; 

     UIAlertView *nointernet = [[UIAlertView alloc] 
            initWithTitle: NSLocalizedString(@"No internet connection", nil) 
            message: NSLocalizedString(@"It seems you are not connected to the internet. in-app purchases require a internet connection. Please connect to the internet and try again.", nil) 
            delegate:nil 
            cancelButtonTitle:@"OK" 
            otherButtonTitles:nil, nil]; 


     [nointernet show]; 

    } else { 

     identifier = @"com.ge0rges.Meme_Jump.24000C"; 
     [self checkForParentPermission]; 

    } 
} 


#pragma mark - Processing payment 

-(void)checkForParentPermission { 

    if ([SKPaymentQueue canMakePayments]) { 
     if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.4000C"]) { 

      SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:@"com.ge0rges.Meme_Jump.4000C"]]; 

      request.delegate = self; 

      [request start]; 

      [activityindicatorButton4000 startAnimating]; 
      activityindicatorButton4000.hidden = NO; 

     } else if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.9000C"]) { 

      SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:@"com.ge0rges.Meme_Jump.9000C"]]; 

      request.delegate = self; 

      [request start]; 

      [activityindicatorButton9000 startAnimating]; 
      activityindicatorButton9000.hidden = NO; 

     } else if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.24000C"]) { 

      SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:@"com.ge0rges.Meme_Jump.24000C"]]; 

      request.delegate = self; 

      [request start]; 

      [activityindicatorButton24000 startAnimating]; 
      activityindicatorButton24000.hidden = NO; 
     } 

    } else { 

     UIAlertView *tmp = [[UIAlertView alloc] 
          initWithTitle:NSLocalizedString(@"Prohibited", nil) 
          message:NSLocalizedString(@"Sorry , Parental Control has prohibited in-app purchases, you cannot make a purchase.", nil) 
          delegate:nil 
          cancelButtonTitle:@"Ok" 
          otherButtonTitles:nil, nil]; 
     [tmp show]; 

    } 
} 

-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response 

{ 

    if (forButtonsAndLabels == YES && internetActive == YES && forPurchase == NO) { 

     [activityindicatorButton4000 stopAnimating]; 
     [activityindicatorButton9000 stopAnimating]; 
     [activityindicatorButton24000 stopAnimating]; 

     product1 = nil; 
     product2 = nil; 
     product3 = nil; 

     int count = (int)[response.products count]; 

     if (count>0) { 
      NSLog(@"%i", count); 
      product1 = [response.products objectAtIndex:1]; 
      product2 = [response.products objectAtIndex:2]; 
      product3 = [response.products objectAtIndex:0]; 

      NSNumberFormatter *numberFormatter1 = [[NSNumberFormatter alloc] init]; 
      [numberFormatter1 setFormatterBehavior:NSNumberFormatterBehavior10_4]; 
      [numberFormatter1 setNumberStyle:NSNumberFormatterCurrencyStyle]; 
      [numberFormatter1 setLocale:product1.priceLocale]; 
      NSString *stringPrice1 = [numberFormatter1 stringFromNumber:product1.price]; 

      NSNumberFormatter *numberFormatter2 = [[NSNumberFormatter alloc] init]; 
      [numberFormatter2 setFormatterBehavior:NSNumberFormatterBehavior10_4]; 
      [numberFormatter2 setNumberStyle:NSNumberFormatterCurrencyStyle]; 
      [numberFormatter2 setLocale:product2.priceLocale]; 
      NSString *stringPrice2 = [numberFormatter2 stringFromNumber:product2.price]; 

      NSNumberFormatter *numberFormatter3 = [[NSNumberFormatter alloc] init]; 
      [numberFormatter3 setFormatterBehavior:NSNumberFormatterBehavior10_4]; 
      [numberFormatter3 setNumberStyle:NSNumberFormatterCurrencyStyle]; 
      [numberFormatter3 setLocale:product3.priceLocale]; 
      NSString *stringPrice3 = [numberFormatter3 stringFromNumber:product3.price]; 

      [CoinsButton4000 setTitle:stringPrice1 forState:UIControlStateNormal]; 
      [CoinsButton9000 setTitle:stringPrice2 forState:UIControlStateNormal]; 
      [CoinsButton24000 setTitle:stringPrice3 forState:UIControlStateNormal]; 

      CoinsButton4000.hidden = NO; 
      CoinsButton9000.hidden = NO; 
      CoinsButton24000.hidden = NO; 

      CoinsLabel4000.adjustsFontSizeToFitWidth = NO; 
      CoinsLabel9000.adjustsFontSizeToFitWidth = NO; 
      CoinsLabel24000.adjustsFontSizeToFitWidth = NO; 

      CoinsLabel4000.numberOfLines = 1; 
      CoinsLabel9000.numberOfLines = 1; 
      CoinsLabel24000.numberOfLines = 1; 


      [CoinsLabel4000 setText:product1.localizedTitle]; 
      [CoinsLabel9000 setText:product2.localizedTitle]; 
      [CoinsLabel24000 setText:product3.localizedTitle]; 

      fakePurchase = YES; 

     } else { 

      [CoinsButton4000 setTitle:NSLocalizedString(@"N/A", nil) forState:UIControlStateNormal]; 
      [CoinsButton9000 setTitle:NSLocalizedString(@"N/A", nil) forState:UIControlStateNormal]; 
      [CoinsButton24000 setTitle:NSLocalizedString(@"N/A", nil) forState:UIControlStateNormal]; 

      [CoinsLabel4000 setText:nil]; 
      [CoinsLabel9000 setText:nil]; 
      [CoinsLabel24000 setText:nil]; 

      CoinsButton4000.hidden = NO; 
      CoinsButton9000.hidden = NO; 
      CoinsButton24000.hidden = NO; 

      [activityindicatorButton24000 stopAnimating]; 
      [activityindicatorButton4000 stopAnimating]; 
      [activityindicatorButton9000 stopAnimating]; 

      forButtonsAndLabels = YES; 
      forPurchase = NO; 
      fakePurchase = YES; 

     } 

    } else if (forPurchase == YES && internetActive == YES && fakePurchase == NO) { 

     validProduct = nil; 

     int count = (int)[response.products count]; 

     if (count>0) { 

      validProduct = [response.products objectAtIndex:0]; 

      SKPayment *payment = [SKPayment paymentWithProduct:validProduct]; 

      [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; 

      [[SKPaymentQueue defaultQueue] addPayment:payment]; // <-- KA CHING! 


     } else { 

      UIAlertView *notAvail = [[UIAlertView alloc] 
            initWithTitle:NSLocalizedString(@"Failed", nil) 
            message:NSLocalizedString(@"Sorry there seems to be a problem. Please try again later.", nil) 
            delegate:nil 
            cancelButtonTitle:@"Ok" 
            otherButtonTitles:nil, nil]; 

      [notAvail show]; 

     } 

    } else { 

     [CoinsButton4000 setTitle:NSLocalizedString(@"N/A", nil) forState:UIControlStateNormal]; 
     [CoinsButton9000 setTitle:NSLocalizedString(@"N/A", nil) forState:UIControlStateNormal]; 
     [CoinsButton24000 setTitle:NSLocalizedString(@"N/A", nil) forState:UIControlStateNormal]; 

     [CoinsLabel4000 setText:nil]; 
     [CoinsLabel9000 setText:nil]; 
     [CoinsLabel24000 setText:nil]; 

     CoinsButton4000.hidden = NO; 
     CoinsButton9000.hidden = NO; 
     CoinsButton24000.hidden = NO; 

     [activityindicatorButton24000 stopAnimating]; 
     [activityindicatorButton4000 stopAnimating]; 
     [activityindicatorButton9000 stopAnimating]; 

     forButtonsAndLabels = YES; 
     forPurchase = NO; 
     fakePurchase = YES; 
    } 
} 

-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { 
    for (SKPaymentTransaction *transaction in transactions) { 
     switch (transaction.transactionState) { 
      case SKPaymentTransactionStatePurchasing: 
      { 
       if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.4000C"]) { 

        [activityindicatorButton4000 startAnimating]; 
        activityindicatorButton4000.hidden = NO; 

       } else if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.9000C"]) { 

        [activityindicatorButton9000 startAnimating]; 
        activityindicatorButton9000.hidden = NO; 

       } else if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.24000C"]) { 

        [activityindicatorButton24000 startAnimating]; 
        activityindicatorButton24000.hidden = NO; 

       } 

       break; 
      } 

      case SKPaymentTransactionStatePurchased: 
      { 
       [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; 

       int receiptValue = (int)[self verifyReceipt:transaction]; 

       if (receiptValue == 0) { 

        if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.4000C"]) { 

         CoinsButton4000.hidden = NO; 
         [activityindicatorButton4000 stopAnimating]; 

         UIAlertView *complete = [[UIAlertView alloc] 
               initWithTitle:NSLocalizedString(@"Complete", nil) 
               message:NSLocalizedString(@"You have received 4000 Coins.", nil) 
               delegate:nil 
               cancelButtonTitle:NSLocalizedString(@"Awesome!", nil) 
               otherButtonTitles:nil, nil]; 
         [complete show]; 

         allCoins += 4000; 

         [self setItUp]; 

        } else if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.9000C"]) { 

         CoinsButton9000.hidden = NO; 
         [activityindicatorButton9000 stopAnimating]; 

         UIAlertView *complete = [[UIAlertView alloc] 
               initWithTitle:NSLocalizedString(@"Complete", nil) 
               message:NSLocalizedString(@"You have received 9000 Coins.", nil) 
               delegate:nil 
               cancelButtonTitle:NSLocalizedString(@"Awesome!", nil) 
               otherButtonTitles:nil, nil]; 
         [complete show]; 

         allCoins += 9000; 

         [self setItUp]; 

        } else if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.24000C"]) { 

         CoinsButton24000.hidden = NO; 
         [activityindicatorButton24000 stopAnimating]; 

         UIAlertView *complete = [[UIAlertView alloc] 
               initWithTitle:NSLocalizedString(@"Complete", nil) 
               message:NSLocalizedString(@"You have received 24000 Coins.", nil) 
               delegate:nil 
               cancelButtonTitle:NSLocalizedString(@"Awesome!", nil) 
               otherButtonTitles:nil, nil]; 
         [complete show]; 

         allCoins += 24000; 

         [self setItUp]; 

        } 

       } else { 


        UIAlertView *failed = [[UIAlertView alloc] 
              initWithTitle:NSLocalizedString(@"Receipt Invalid", nil) 
              message:NSLocalizedString(@"The receipt could not be verified. If you are jailbroken please check for tweaks that may interfere with connection to iTunes or provide free in-app purchases 'like IAP-Cracker', otherwise check your internet connection. And don't worry you have not been charged", nil) 
              delegate:nil 
              cancelButtonTitle:@"Ok" 
              otherButtonTitles:nil, nil]; 
        [failed show]; 


        if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.4000C"]) { 

         CoinsButton4000.hidden = NO; 
         [activityindicatorButton4000 stopAnimating]; 

        } else if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.9000C"]) { 

         CoinsButton9000.hidden = NO; 
         [activityindicatorButton9000 stopAnimating]; 

        } else if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.24000C"]) { 

         CoinsButton24000.hidden = NO; 
         [activityindicatorButton24000 stopAnimating]; 

        } 

       } 

       break; 
      } 

      case SKPaymentTransactionStateRestored: 
      { 

       [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; 

       if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.4000C"]) { 

        CoinsButton4000.hidden = NO; 
        [activityindicatorButton4000 stopAnimating]; 

       } else if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.9000C"]) { 

        CoinsButton9000.hidden = NO; 
        [activityindicatorButton9000 stopAnimating]; 

       } else if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.24000C"]) { 

        CoinsButton24000.hidden = NO; 
        [activityindicatorButton24000 stopAnimating]; 

       } 

       break; 
      } 

      case SKPaymentTransactionStateFailed: 
      { 
       if (transaction.error.code != SKErrorPaymentCancelled && forPurchase == YES && fakePurchase == NO) { 

        UIAlertView *failed = [[UIAlertView alloc] 
              initWithTitle:NSLocalizedString(@"Failed", nil) 
              message:transaction.error.localizedDescription 
              delegate:nil 
              cancelButtonTitle:@"Ok" 
              otherButtonTitles:nil, nil]; 
        [failed show]; 


       } 

       [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; 

       if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.4000C"]) { 

        CoinsButton4000.hidden = NO; 
        [activityindicatorButton4000 stopAnimating]; 

       } else if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.9000C"]) { 

        CoinsButton9000.hidden = NO; 
        [activityindicatorButton9000 stopAnimating]; 

       } else if ([identifier isEqualToString:@"com.ge0rges.Meme_Jump.24000C"]) { 

        CoinsButton24000.hidden = NO; 
        [activityindicatorButton24000 stopAnimating]; 

       } 

       fakePurchase = NO; 

       break; 
      } 
     } 
    } 
} 

#pragma mark - verifying purchases 

- (NSInteger)verifyReceipt:(SKPaymentTransaction *)transaction { 

    NSString *jsonObjectString = [self encode:(uint8_t *)transaction.transactionReceipt.bytes length:transaction.transactionReceipt.length]; 
    NSString *completeString = [NSString stringWithFormat:@"http://ge0rges.com/verifyiap/verifyiap.php?receipt=%@", jsonObjectString]; 

    NSURL *urlForValidation = [NSURL URLWithString:completeString]; 

    NSMutableURLRequest *validationRequest = [[NSMutableURLRequest alloc] initWithURL:urlForValidation]; 
    [validationRequest setHTTPMethod:@"GET"]; 

    NSData *responseData = [NSURLConnection sendSynchronousRequest:validationRequest returningResponse:nil error:nil]; 

    NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]; 

    NSInteger response = [responseString integerValue]; 

    return response; 
} 

- (NSString *)encode:(const uint8_t *)input length:(NSInteger)length { 

    static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/="; 

    NSMutableData *data = [NSMutableData dataWithLength:((length + 2)/3) * 4]; 
    uint8_t *output = (uint8_t *)data.mutableBytes; 

    for (NSInteger i = 0; i < length; i += 3) { 
     NSInteger value = 0; 
     for (NSInteger j = i; j < (i + 3); j++) { 
      value <<= 8; 

      if (j < length) { 
       value |= (0xFF & input[j]); 
      } 
     } 

     NSInteger index = (i/3) * 4; 
     output[index + 0] =     table[(value >> 18) & 0x3F]; 
     output[index + 1] =     table[(value >> 12) & 0x3F]; 
     output[index + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '='; 
     output[index + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '='; 
    } 

    return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; 
} 

- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

- (void)viewDidUnload { 
    [super viewDidUnload]; 

    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
} 

@end 
+0

檢查iTunesConnect中是否有崩潰日誌。構建應用程序的發佈版本並自行嘗試。 – Wain

+0

我構建了一個發佈版本,並且崩潰出現了。至於iTunes連接我已經檢查,但沒有得到任何東西... – ge0rges

+0

您需要對它進行符號化,以便在代碼崩潰時看到它的位置,然後將代碼的那部分發布在崩潰的位置,如果無法自己弄清楚的話。 – Kerni

回答

0

根據您的崩潰,看起來比你期望你SKProductsRequest將返回較少的項目,你所訪問過返回數組的結束。在訪問數組之前,您應該確認該數組的大小。

至於數組可能小於預期的原因,您應該在iTunes Connect中查找有關IAP調試提示的IAP或Google的任何問題。

+0

除此之外,'SKProductsRequest'只會在實時App Store版本上返回** Review ** IAP,而開發版本則可以全部訪問它們。因此,當您嘗試訪問包含產品的「NSArray」時,它會顯示您的應用程序認爲更多產品,並且您收到越界異常。您是否提交了所有IAP以供審覈?或者您的發佈版本是否包含試圖訪問測試IAP的調試代碼? –

+0

請參閱編輯的問題 – ge0rges

+0

我不確定你在問什麼。您可能想要提供更多細節,或者可能打開一個單獨的問題。 –