我已将InApp Purchasing添加到我的应用中,但在尝试使用测试用户帐户完成测试事务时,应用程序会在以下代码中继续崩溃,说明发送到实例的无法识别的选择器。
我已经阅读了这篇文章,并认为这可能与我使用Auto Renewal Subscription产品的事实有关。
似乎与崩溃有关的代码就是这一行:
[[NSNotificationCenter defaultCenter] postNotificationName:@"TransCancel" object: self];
我已经提供了我的InAppPurchase代码,任何人都可以请你帮我这个!!
InAppPurchaseSS.h
#import <Foundation/Foundation.h>
#import "StoreKit/StoreKit.h"
#define kProductPurchasedNotification @"ProductPurchased"
#define kProductPurchaseFailedNotification @"ProductPurchaseFailed"
#define kProductPurchaseCancelledNotification @"ProductPurchaseCancelled"
@interface InAppPurchaseSS : NSObject <SKProductsRequestDelegate,SKPaymentTransactionObserver,UIAlertViewDelegate>
{
SKProductsRequest* productsRequest;
SKProduct *proUpgradeProduct;
UIAlertView* waitingAlert;
BOOL isTransactionOngoing;
}
@property (retain) SKProductsRequest* productsRequest;
@property (retain) NSArray * products;
@property (retain) SKProductsRequest *request;
@property (assign) BOOL isTransactionOngoing;
+ (InAppPurchaseSS *) sharedHelper;
-(id)init;
- (void)buyProductIdentifier:(NSString *)productIdentifier;
- (BOOL)canMakePurchases;
-(void)restoreInAppPurchase;
- (void)collectProducts;
@end
InAppPurchaseSS.m
#import "InAppPurchaseSS.h"
#import "Reachability.h"
@implementation InAppPurchaseSS
@synthesize products;
@synthesize request;
@synthesize productsRequest;
@synthesize isTransactionOngoing;
static InAppPurchaseSS * _sharedHelper;
+ (InAppPurchaseSS *) sharedHelper {
if (_sharedHelper != nil) {
return _sharedHelper;
}
_sharedHelper = [[InAppPurchaseSS alloc] init];
return _sharedHelper;
}
-(id)init {
if( (self=[super init]))
{
isTransactionOngoing=NO;
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}
return self;
}
- (void)collectProducts
{
self.request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:@"my.inappads"]];
self.request.delegate = self;
[self.request start];
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSLog(@"Received products results...");
self.products = response.products;
self.request = nil;
NSLog(@"Number of product:%i : %@",[response.products count],response.products);
NSArray *product = response.products;
proUpgradeProduct = [product count] == 1 ? [[product firstObject] retain] : nil;
if (proUpgradeProduct)
{
NSLog(@"Product title: %@" , proUpgradeProduct.localizedTitle);
NSLog(@"Product description: %@" , proUpgradeProduct.localizedDescription);
NSLog(@"Product price: %@" , proUpgradeProduct.price);
NSLog(@"Product id: %@" , proUpgradeProduct.productIdentifier);
}
for (NSString *invalidProductId in response.invalidProductIdentifiers)
{
NSLog(@"Invalid product id: %@" , invalidProductId);
}
}
-(void)restoreInAppPurchase
{
Reachability *reach = [Reachability reachabilityForInternetConnection];
NetworkStatus netStatus = [reach currentReachabilityStatus];
if (netStatus == NotReachable) {
NSLog(@"No internet connection!");
[[[UIAlertView alloc] initWithTitle:@"No Internet" message:@"Sorry, no internet connection found" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil] show];
return;
}
waitingAlert = [[UIAlertView alloc] initWithTitle:@"Restoring..." message:@"Please Wait...\n\n" delegate:nil cancelButtonTitle:nil otherButtonTitles: nil];
[waitingAlert show];
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}
- (void)buyProductIdentifier:(NSString *)productIdentifier {
if ([productIdentifier isEqual: @"my.inappads"]) {
NSLog(@"No IAP Product ID specified");
return;
}
Reachability *reach = [Reachability reachabilityForInternetConnection];
NetworkStatus netStatus = [reach currentReachabilityStatus];
if (netStatus == NotReachable) {
NSLog(@"No internet connection!");
[[[UIAlertView alloc] initWithTitle:@"No Internet" message:@"Sorry, no internet connection found" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil] show];
return;
}
isTransactionOngoing=YES;
waitingAlert = [[UIAlertView alloc] initWithTitle:@"Purchasing..." message:@"Please Wait...\n\n" delegate:nil cancelButtonTitle:nil otherButtonTitles: nil];
[waitingAlert show];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0) {
SKMutablePayment *payment = [[SKMutablePayment alloc] init];
payment.productIdentifier = productIdentifier;
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
else {
SKPayment *payment = [SKPayment paymentWithProductIdentifier:productIdentifier];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
}
-(void)enableFeature
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"PurchaseSuccess"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
{
[waitingAlert dismissWithClickedButtonIndex:0 animated:YES];
NSLog(@"Restore completed transaction failed");
}
- (BOOL)canMakePurchases
{
return [SKPaymentQueue canMakePayments];
}
//
- (void)finishTransaction:(SKPaymentTransaction *)transaction wasSuccessful:(BOOL)wasSuccessful
{
isTransactionOngoing=NO;
[waitingAlert dismissWithClickedButtonIndex:0 animated:YES];
// remove the transaction from the payment queue.
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
if (wasSuccessful)
{
[self enableFeature];
[[[UIAlertView alloc] initWithTitle:@"Congratulations!!" message:@"You have succesfully Purchases." delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil] show];
[[NSNotificationCenter defaultCenter] postNotificationName:@"successbuy" object:self];
}
else
{
[[[UIAlertView alloc] initWithTitle:@"Error!" message:transaction.error.localizedDescription delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil] show];
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
[[NSNotificationCenter defaultCenter] postNotificationName:@"TransCancel" object: self];
}
}
- (void)completeTransaction:(SKPaymentTransaction *)transaction
{
NSLog(@"succesfull transaction");
[self finishTransaction:transaction wasSuccessful:YES];
}
- (void)restoreTransaction:(SKPaymentTransaction *)transaction
{
NSLog(@"transaction is restored");
[self finishTransaction:transaction wasSuccessful:YES];
}
// called when a transaction has failed
- (void)failedTransaction:(SKPaymentTransaction *)transaction
{
isTransactionOngoing=NO;
NSLog(@"failed transaction called");
if (transaction.error.code != SKErrorPaymentCancelled)
{
NSLog(@"Transaction failed called");
NSLog(@"Transaction error: %@", transaction.error.localizedDescription);
[self finishTransaction:transaction wasSuccessful:NO];
}
else
{
[waitingAlert dismissWithClickedButtonIndex:0 animated:YES];
NSLog(@"user cancel transaction");
// this is fine, the user just cancelled, so don’t notify
[[NSNotificationCenter defaultCenter] postNotificationName:@"TransCancel" object: self];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
}
#pragma mark -
#pragma mark SKPaymentTransactionObserver methods
// called when the transaction status is updated
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
NSLog(@"transaction status updated");
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) dealloc
{
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
[super dealloc];
}
@end
我在用户进行购买的视图中使用@TransCancel,代码如下:
//购买
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver: self selector: @selector(TransactionCancel) name:@"TransCancel" object: nil];
[center addObserver: self selector: @selector(TransactionComplete) name:@"successbuy" object: nil];
NSLog(@"%d",[[NSUserDefaults standardUserDefaults] boolForKey:@"PurchaseSuccess"]);
if([[NSUserDefaults standardUserDefaults] boolForKey:@"PurchaseSuccess"])
btn.hidden=YES;
else
btn.hidden=NO;
错误记录
2014-01-06 00:25:40.694 MyApp[2764:60b] transaction status updated
2014-01-06 00:25:40.695 MyApp[2764:60b] failed transaction called
2014-01-06 00:25:40.696 MyApp[2764:60b] Transaction failed called
2014-01-06 00:25:40.696 MyApp[2764:60b] Transaction error: Cannot connect to iTunes Store
2014-01-06 00:25:40.730 MyApp[2764:60b] -[MyViewController TransactionCancel]: unrecognized selector sent to instance 0x1666a350
MyViewController
#import "UpgradeViewController.h"
#import "ECSlidingViewController.h"
#import "MenuViewController.h"
#import "InAppPurchaseSS.h"
#define ProductIdentifier @"<my.inappads>"
@interface UpgradeViewController ()
@property (retain, nonatomic) IBOutlet JSAnimatedImagesView *animatedImagesView;
@property (weak, nonatomic) IBOutlet UIButton *installFullAppButton;
@end
@implementation UpgradeViewController
@synthesize menuBtn, animatedImagesView = _animatedImagesView, scrolly, bannerView, labelPrice;
- (NSString *)publisherIdForAdSdkBannerView:(AdSdkBannerView *)banner {
return @"e0616d4190bff65279ed5c20de1b5653";
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Price
SKProduct *product = [[[InAppPurchaseSS sharedHelper] products] lastObject];
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[numberFormatter setLocale:product.priceLocale];
NSString *formattedString = [numberFormatter stringFromNumber:product.price];
// [self.installFullAppButton setTitle:formattedString forState:UIControlStateNormal];
labelPrice.text = formattedString;
// Purchase
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver: self selector: @selector(TransactionCancel) name:@"TransactionCancel" object: nil];
[center addObserver: self selector: @selector(TransactionComplete) name:@"successbuy" object: nil];
NSLog(@"%d",[[NSUserDefaults standardUserDefaults] boolForKey:@"PurchaseSuccess"]);
if([[NSUserDefaults standardUserDefaults] boolForKey:@"PurchaseSuccess"])
btn.hidden=YES;
else
btn.hidden=NO;
// Do any additional setup after loading the view.
//UIScrollView
self.scrolly.contentSize = CGSizeMake(320, 600);
//Image Transition
// self.animatedImagesView.delegate = self;
self.view.layer.shadowOpacity = 0.75f;
self.view.layer.shadowRadius = 10.0f;
self.view.layer.shadowColor = [UIColor blackColor].CGColor;
if (![self.slidingViewController.underLeftViewController isKindOfClass:[MenuViewController class]]) {
self.slidingViewController.underLeftViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"Menu"];
}
[self.view addGestureRecognizer:self.slidingViewController.panGesture];
self.menuBtn = [UIButton buttonWithType:UIButtonTypeCustom];
menuBtn.frame = CGRectMake(8, 30, 34, 24);
[menuBtn setBackgroundImage:[UIImage imageNamed:@"menuButton.png"] forState:UIControlStateNormal];
[menuBtn addTarget:self action:@selector(revealMenu:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.menuBtn];
myWebView.opaque = NO;
myWebView.backgroundColor = [UIColor clearColor];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)revealMenu:(id)sender
{
[self.slidingViewController anchorTopViewTo:ECRight];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.screenName = @"Upgrade";
}
#pragma mark - Memory Management
- (void)viewDidUnload
{
// [self setAnimatedImagesView:nil];
[self setScrolly:nil];
// [self setAnimatedImagesView:nil];
[super viewDidUnload];
[self setBannerView:nil];
[super viewDidUnload];
}
- (void)dealloc
{
bannerView.delegate = nil;
}
-(IBAction)but:(id)sender
{
[[InAppPurchaseSS sharedHelper] buyProductIdentifier:ProductIdentifier];
}
-(IBAction)restore:(id)sender
{
[[InAppPurchaseSS sharedHelper] restoreInAppPurchase];
}
- (IBAction)dismissView:(id)sender {
[self dismissViewControllerAnimated:YES completion:NULL];
}
-(void)TransactionComplete
{
btn.hidden=YES;
}
-(void)TransactionCancel
{
btn.hidden=NO;
}
答案 0 :(得分:0)
你有这一行:
[center addObserver: self selector: @selector(TransactionCancel) name:@"TransCancel" object: nil];
这意味着self
必须实施TransactionCancel
方法。该错误表示该方法在MyViewController
类中不存在。
解决方案是将TransactionCancel
方法添加到MyViewController
类。