在应用程序购买代码测试期间崩溃

时间:2014-01-05 23:20:47

标签: ios objective-c in-app-purchase unrecognized-selector

我已将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;
}

1 个答案:

答案 0 :(得分:0)

你有这一行:

[center addObserver: self  selector: @selector(TransactionCancel)  name:@"TransCancel" object: nil];

这意味着self必须实施TransactionCancel方法。该错误表示该方法在MyViewController类中不存在。

解决方案是将TransactionCancel方法添加到MyViewController类。