业余人士。按下“购买”按钮时,代码效果很好(我使用断点来挑选有问题的行,见下文),直到调用canMakePayments
为止。处理IAP的场景包括Gamescene
,InAppManager
,InAppObserver
,ORPurchaseProduct
;所有相关代码如下。
我的应用在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)
这就是InAppPurchase.m中的整个代码的样子
@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];
}
这是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!");
}
答案 0 :(得分:0)
我注释掉了这行代码,一切顺利,它出现在AppDelegate的applicationWillResignActive方法中。谢谢你们。
SKView *view = (SKView *)self.window.rootViewController.view;
((GameScene *)view.scene).gamePaused = YES;