2015-01-03 2 views
-2

아마추어가 여기 있습니다. 코드는 canMakePayments이 호출 될 때까지 BUY 버튼을 누르면 잘 작동합니다 (문제가있는 라인을 선택하기 위해 중단 점을 사용했습니다, 아래 참조). IAP를 관리하는 장면은 Gamescene, InAppManager, InAppObserver, ORPurchaseProduct입니다. 모든 관련 코드는 아래에 제공됩니다.in-App purchase can meakePayments라고 부른 후 앱이 멈추고 충돌합니다.

break 이후에 내 앱이 다운됩니다. 모든 것은 break 줄까지 작동합니다. 내부는 InAppManager.m입니다. 아래로 스크롤하여 InAppManager.m에있는 모든 코드를 확인하십시오. 앱이 다운 된 후 IAP 정렬은 계속해서 alertView를 표시하여 구매를 요청합니다. 구매를 클릭하면 alertView가 사라지고 앱이 모든 터치에 응답하지 않습니다. 앱을 닫고 열면 제품을 구입 한 것으로 표시되며 모든 것이 제대로 작동합니다. 모든 정보를 공유했습니다. 미리 감사드립니다.

누군가 내게 지침을 보여 주실 수 있습니까?

-(void) buyFeature:(NSString*) featureID { 

    if ([SKPaymentQueue canMakePayments]) { 
     NSLog(@"Can make payments"); 
     SKProduct* selectedProduct; 

     for (int i=0; i < [purchaseableProducts count]; i++) { 
      selectedProduct = [purchaseableProducts objectAtIndex:i]; 

      if ([[selectedProduct productIdentifier] isEqualToString:featureID]) { 

       // if we found a SKProduct in the purchaseableProducts array with the same ID as the one we want to buy, we proceed by putting it in the payment queue. 

       SKPayment* payment = [SKPayment paymentWithProduct:selectedProduct]; 
       [[SKPaymentQueue defaultQueue] addPayment:payment]; 

       NSLog(@"Proceeding by putting the product in the payment queue"); 

       break; 

      } 
      else { 

       UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Sorry" message:@"You can't purchase from the App Store" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
       [alert show]; 

      } 

     } 
    } 
} 

이것은 충돌 후 콘솔에서와 같은 모습입니다

2015-01-03 20:51:09.244 My App Name[1785:95544] Proceeding by putting the product in the payment queue 
2015-01-03 20:51:10.369 My App Name[1785:95544] -[ORPurchaseProduct setGamePaused:]: unrecognized selector sent to instance 0x7fcf9b417ce0 
2015-01-03 20:51:10.389 My App Name[1785:95544] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ORPurchaseProduct setGamePaused:]: unrecognized selector sent to instance 0x7fcf9b417ce0' 
*** First throw call stack: 
(
    0 CoreFoundation      0x000000010ed55f35 __exceptionPreprocess + 165 
    1 libobjc.A.dylib      0x000000010e697bb7 objc_exception_throw + 45 
    2 CoreFoundation      0x000000010ed5d04d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205 
    3 CoreFoundation      0x000000010ecb527c ___forwarding___ + 988 
    4 CoreFoundation      0x000000010ecb4e18 _CF_forwarding_prep_0 + 120 
    5 My App Name       0x000000010dcd3d88 -[AppDelegate applicationWillResignActive:] + 216 
    6 UIKit        0x000000010f535d96 -[UIApplication _deactivateForReason:notify:] + 338 
    7 CoreFoundation      0x000000010ed25cec __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12 
    8 CoreFoundation      0x000000010ecdf72e ____CFXNotificationPostToken_block_invoke + 142 
    9 CoreFoundation      0x000000010ec8b53c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12 
    10 CoreFoundation      0x000000010ec81285 __CFRunLoopDoBlocks + 341 
    11 CoreFoundation      0x000000010ec80a67 __CFRunLoopRun + 887 
    12 CoreFoundation      0x000000010ec80486 CFRunLoopRunSpecific + 470 
    13 GraphicsServices     0x0000000110dee9f0 GSEventRunModal + 161 
    14 UIKit        0x000000010f53b420 UIApplicationMain + 1282 
    15 My App Name       0x000000010dcfaf03 main + 115 
    16 libdyld.dylib      0x00000001111da145 start + 1 
    17 ???         0x0000000000000001 0x0 + 1 
) 
libc++abi.dylib: terminating with uncaught exception of type NSException 
(lldb) 

이이 어떻게 전체가

@interface InAppManager() { 

    NSMutableArray* purchaseableProducts; // an array of possible products to purchase 
    NSUserDefaults* defaults; // store a bool variable marking products that have been unlocked 
    bool product1WasPurchased; // YES or NO 

    InAppObserver* theObserver; 

} 

@end 

@implementation InAppManager 

static NSString* productID1 = @"MyProduct"; 


static InAppManager* sharedManager = nil; 

+(InAppManager*) sharedManager { 

    if(sharedManager == nil) { 

     sharedManager = [[InAppManager alloc] init]; 

    } 

    return sharedManager; 
} 

-(id) init { 

    if ((self = [super init])) { 

     //do initialization 

     sharedManager = self; 
     defaults = [NSUserDefaults standardUserDefaults]; 
     product1WasPurchased = [defaults boolForKey:productID1]; 


     purchaseableProducts = [[NSMutableArray alloc] init]; 
     [self requestProductData]; 

     theObserver = [[InAppObserver alloc] init]; 
     [[SKPaymentQueue defaultQueue] addTransactionObserver:theObserver]; 
    } 

    return self; 

} 

-(void) requestProductData { 

    SKProductsRequest* request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObjects:productID1, nil]]; 

    request.delegate = self; 
    [request start]; 
} 


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



    NSArray* skProducts = response.products; 

    if ([skProducts count] != 0 && [purchaseableProducts count] == 0) { 

     for (int i = 0; i < [skProducts count]; i++) { 

      [purchaseableProducts addObject:[skProducts objectAtIndex:i]]; 
      SKProduct* product = [purchaseableProducts objectAtIndex:i]; 

      NSLog(@"Feature: %@, Cost: %f, ID: %@", [product localizedTitle], [[product price] doubleValue], [product productIdentifier]); 

     } 

    } 

    NSLog(@" We found %lu In-App Purchases in iTunes Connect", (unsigned long)[purchaseableProducts count]); 

} 


-(void) failedTransaction:(SKPaymentTransaction*) transaction{ 

    NSString* failMessage = [NSString stringWithFormat:@"Reason: %@, You can try: %@", [transaction.error localizedFailureReason], [transaction.error localizedRecoverySuggestion] ]; 

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Unable to complete your purchase" message:failMessage delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
    [alert show]; 


} 
-(void) provideContent:(NSString*) productIdentifier{ 


    NSNotificationCenter* notification = [NSNotificationCenter defaultCenter]; 

    if ([productIdentifier isEqualToString:productID1]) { 
     product1WasPurchased = YES; 
     [defaults setBool:YES forKey:productID1]; 
     [notification postNotificationName:@"feature1Purchased" object:nil]; 

     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Thank you!" message:@"You have purchased MyProduct" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
     [alert show]; 

    } 
    else { 
     NSLog(@"Error: Something happened!"); 
    } 


} 


-(void) buyFeature1 { 

    [self buyFeature:productID1]; 

} 

-(void) buyFeature:(NSString*) featureID { 

    if ([SKPaymentQueue canMakePayments]) { 
     NSLog(@"Can make payments"); 
     SKProduct* selectedProduct; 

     for (int i=0; i < [purchaseableProducts count]; i++) { 
      selectedProduct = [purchaseableProducts objectAtIndex:i]; 

      if ([[selectedProduct productIdentifier] isEqualToString:featureID]) { 

       SKPayment* payment = [SKPayment paymentWithProduct:selectedProduct]; 
       [[SKPaymentQueue defaultQueue] addPayment:payment]; 

       NSLog(@"Proceeding by putting the product in the payment queue"); 

       break; 

      } 
      else { 

       UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Oh no" message:@"You can't purchase from the App Store" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
       [alert show]; 

      } 

     } 
    } 
} 

-(bool) isFeature1PurchasedAlready { 

    return product1WasPurchased; 
} 


-(void) restoreCompletedTransactions{ 

    [[SKPaymentQueue defaultQueue] restoreCompletedTransactions]; 

} 

처럼 InAppPurchase.m의 전체 코드는 모습입니다 InAppObserver.m의 코드입니다.

#import "InAppObserver.h" 
#import "InAppManager.h" 

@implementation InAppObserver 

-(void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { 

    NSLog(@"Payment queue options"); 

    for(SKPaymentTransaction *transaction in transactions) { 

     switch (transaction.transactionState) { 
      case SKPaymentTransactionStatePurchased: 
       [self completeTransaction:transaction]; 
       break; 
      case SKPaymentTransactionStateFailed: 
       [self failedTransaction:transaction]; 
       break; 
      case SKPaymentTransactionStateRestored: 
       [self restoreTransaction:transaction]; 
       break; 

      default: 
       break; 
     } 

    } 

} 

-(void)failedTransaction:(SKPaymentTransaction*) transaction { 
    NSLog(@"Transaction Failed"); 

    //if the error was anything other than the user cancelling it 

    if (transaction.error.code != SKErrorPaymentCancelled) { 

     [[InAppManager sharedManager] failedTransaction:transaction]; 

     NSLog(@"%@", [transaction.error localizedDescription]); 

    } 

    [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; 

} 

-(void)completeTransaction:(SKPaymentTransaction*) transaction { 
    NSLog(@"Transaction Completion"); 

    //when we pass the transaction back to the sharedManager it has the product ID 

    [[InAppManager sharedManager] provideContent:transaction.payment.productIdentifier]; 

    [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; 
} 

-(void)restoreTransaction:(SKPaymentTransaction*) transaction { 
    NSLog(@"Transaction Restored"); 

    [[InAppManager sharedManager] provideContent:transaction.originalTransaction.payment.productIdentifier]; 
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; 
} 

@end 

나는 GameScene에이 라인들을 가지고 있는데, 모든 것이 시작되는 곳에서, 나는 관련 코드만을 선택했다.

-(void)didMoveToView:(SKView *)view { 
    /* Setup your scene here */ 

[InAppManager sharedManager]; 

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(unlockProduct1) name:@"feature1Purchased" object:nil]; 
} 

-(void) unlockProduct1 { 

    NSLog(@"this class knows we purchased the product!"); 

} 

이 줄들은 ORPurchaseProduct.m에 있습니다. 여기에는 구매 버튼이 있으며 제품을 이미 구입했는지 확인합니다. 나는 GameScene에서 이것을 전환한다.

-(void)didMoveToView:(SKView *)view 
{ 
[InAppManager sharedManager]; 

if ([[InAppManager sharedManager] isFeature1PurchasedAlready] == NO) { 
    NSLog(@" product was not bought yet"); 
    [self createBuyButton:@"BUY"]; 

} else { 
    NSLog(@" product was bought"); 
    [self createBuyButton:alreadyBoughtMessage]; 
} 
} 

-(void) createBuyButton:(NSString*) theMessage { 

    UIFont* theFont = [UIFont fontWithName:@"BUY" size:18]; 

    thePurchaseButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 

    if([theMessage isEqualToString:alreadyBoughtMessage]) { 

     [thePurchaseButton addTarget:self action:@selector(doNothing) forControlEvents:UIControlEventTouchUpInside]; 

     NSLog(@"Already bought message: we are here"); 

    } else { 

     [thePurchaseButton addTarget:[InAppManager sharedManager] action:@selector(buyFeature1) forControlEvents:UIControlEventTouchUpInside]; 
    } 

    [thePurchaseButton.titleLabel setFont:theFont]; 
    [thePurchaseButton setTitle:theMessage forState:UIControlStateNormal]; 
    [thePurchaseButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 
    [thePurchaseButton setBackgroundColor:[UIColor blackColor]]; 
    thePurchaseButton.frame = CGRectMake(80, 380, 160, 30); 
    [self.view addSubview:thePurchaseButton];  
} 

-(void)doNothing 
{ 
    NSLog(@"Nothing to be done because the product is already bought!"); 
} 
+1

충돌 로그는 setGamePaused'호출 할 것을 제안하는 AppDelegate에의 applicationWillResignActive method.Thank에 있었다 : '또는 'ORPurchaseProduct' 인스턴스에'gamePaused'라는 변수를 설정하십시오. 예외 중단 점을 추가하고 예외가 throw 된 위치를 확인하십시오. – AMI289

+0

@ AMI289이 코드는 applicationWillResignActive (AppDelegate.m)에 있습니다. SKView * view = (SKView *) self.window.rootViewController.view; ((GameScene *) view.scene) .gamePaused = YES;'또한 GameScene에서 알 수 있듯이이 행에 있습니다. 어쩌면이 문제가이 문제에서 비롯되었을 수도 있지만 문제를 파악할 수는 없습니다. –

답변

0

내가 코드 줄에서 주석 모든 것이 잘되었다, 그것은 너희들

SKView *view = (SKView *)self.window.rootViewController.view; 
((GameScene *)view.scene).gamePaused = YES;