菜鸟教程小白 发表于 2022-12-13 09:50:52

ios - 购买应用内购买后保存更改


                                            <p>我在我的应用程序中有一个应用程序内购买用于删除广告横幅,当我成功购买并返回到我的主 ViewController 时,广告没有删除但是当我退出应用程序并重新打开它时,广告消失了并保持消失。几乎就像它记得我在下一次加载时购买了删除广告 IAP,但不是在购买后立即购买。一个非常聪明的人告诉我我需要这样做:<br><br> <blockquote>
<p>So now all you have to do is call the code that is located in the
viewWillAppear / viewDidLoad methods once you return to your VC after
purchasing the IAP. How you do that is up to you. If you need help
with that I would suggest asking a new question since this comment
thread is getting very long. I&#39;d appreciate if you upvote my answer
and choose it as the correct answer since I&#39;ve helped you get this
working.</p>
</blockquote><br><br>关于如何做到这一点的任何想法?<br><br>谢谢!<br><br>这是我的主 ViewController 的屏幕截图:<br><br> ViewController .h<br><pre><code>#import &lt;UIKit/UIKit.h&gt;
#import &lt;StoreKit/StoreKit.h&gt;
#import &lt;CoreMotion/CoreMotion.h&gt;
#import &lt;CoreLocation/CoreLocation.h&gt;
#import &lt;MapKit/MapKit.h&gt;


@interface ViewController : UIViewController &lt;UIWebViewDelegate, MKMapViewDelegate, CLLocationManagerDelegate&gt;

@property (strong, nonatomic) IBOutlet UIWebView *viewWeb;
@property (nonatomic, strong) CLLocationManager *locationManager;
@property (nonatomic, strong) CLLocation *currentLocation;
@property (weak, nonatomic) IBOutlet UIImageView *PokeABowlAd;


@end
</code></pre><br> ViewController .m:<br><pre><code>#define SHOW_ADS_KEY @&#34;Show Ads Key&#34;
#define k_Save @&#34;Saveitem&#34;


#import &#34;ViewController.h&#34;
#import &lt;AVFoundation/AVFoundation.h&gt;

@interface ViewController () &lt;UITextViewDelegate&gt;


@end

@implementation ViewController

@synthesize viewWeb;

- (void)viewDidLoad {
;

UIBarButtonItem *backButtonItem = [ initWithTitle:@&#34;&#34; style:UIBarButtonItemStylePlain target:nil action:nil];
;


NSString *fullURL = @&#34;https://www.google.com&#34;;
NSURL *url = ;
NSURLRequest *requestObj = ;
viewWeb.scalesPageToFit = YES;
viewWeb.scrollView.bounces = NO;
;
}

#pragma mark - CLLocationManagerDelegate
// Wait for location callbacks
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(@&#34;%@&#34;, );
}

-(void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event {

if (event.type == UIEventSubtypeMotionShake) {
    NSString *jsString = URLForResource:@&#34;iitc&#34; withExtension:@&#34;js&#34;] encoding:NSUTF8StringEncoding error:nil];
    ;
}
}



- (NSUInteger)supportedInterfaceOrientations {
if ([ userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
    return UIInterfaceOrientationMaskAllButUpsideDown;
} else {
    return UIInterfaceOrientationMaskAll;
}
}


- (IBAction)PokeABowlAd:(id)sender {
if (![[ objectForKey:SHOW_ADS_KEY]isEqualToString: @&#34;No&#34;]){ // NEW CODE
    // Code to show ads
    _PokeABowlAd.hidden = NO;

    [ openURL:];
} else {
    _PokeABowlAd.hidden = YES;
}
NSLog(@&#34;Shows ads?: %@&#34;, [ objectForKey:SHOW_ADS_KEY]);

}

- (void)viewWillAppear {
if (![[ objectForKey:SHOW_ADS_KEY] isEqualToString: @&#34;No&#34;]){ // NEW CODE
    // Code to show ads
    _PokeABowlAd.hidden = NO;

} else {
    _PokeABowlAd.hidden = YES;
}
NSLog(@&#34;Shows ads?: %@&#34;, [ objectForKey:SHOW_ADS_KEY]);
}


@end
</code></pre><br>MasterViewController.m:<br><pre><code>    #import &#34;MasterViewController.h&#34;
#import &#34;DetailViewController.h&#34;
#import &#34;RageIAPHelper.h&#34;
#import &lt;StoreKit/StoreKit.h&gt;

@interface MasterViewController () {
NSArray *_products;
NSNumberFormatter * _priceFormatter;
}
@end

@implementation MasterViewController

- (void)viewDidLoad
{
;

UIBarButtonItem *backButtonItem = [ initWithTitle:@&#34;&#34; style:UIBarButtonItemStylePlain target:nil action:nil];
;

self.title = @&#34;Settings&#34;;

self.refreshControl = [ init];
;
;
;

_priceFormatter = [ init];
;
;

self.navigationItem.rightBarButtonItem = [ initWithTitle:@&#34;Restore&#34; style:UIBarButtonItemStylePlain target:self action:@selector(restoreTapped:)];

}

- (void)restoreTapped:(id)sender {
[ restoreCompletedTransactions];
}

- (void)viewWillAppear:(BOOL)animated {
[ addObserver:self selector:@selector(productPurchased:) name:IAPHelperProductPurchasedNotification object:nil];
}

- (void)viewWillDisappear:(BOOL)animated {
[ removeObserver:self];
}

- (void)productPurchased:(NSNotification *)notification {

NSString * productIdentifier = notification.object;
[_products enumerateObjectsUsingBlock:^(SKProduct * product, NSUInteger idx, BOOL *stop) {
    if () {
      ] withRowAnimation:UITableViewRowAnimationFade];
      *stop = YES;
    }
}];

}

- (void)reload {
_products = nil;
;
[ requestProductsWithCompletionHandler:^(BOOL success, NSArray *products) {
    if (success) {
      _products = products;
      ;
    }
    ;
}];
}

#pragma mark - Table View

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _products.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = ;

SKProduct * product = (SKProduct *) _products;
cell.textLabel.text = product.localizedTitle;
;
cell.detailTextLabel.text = ;

if ([ productPurchased:product.productIdentifier]) {
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
    cell.accessoryView = nil;
} else {
    UIButton *buyButton = ;
    buyButton.frame = CGRectMake(0, 0, 72, 37);
    ;
    buyButton.tag = indexPath.row;
    ;
    cell.accessoryType = UITableViewCellAccessoryNone;
    cell.accessoryView = buyButton;
}

return cell;
}

- (void)buyButtonTapped:(id)sender {

UIButton *buyButton = (UIButton *)sender;
SKProduct *product = _products;

NSLog(@&#34;Buying %@...&#34;, product.productIdentifier);
[ buyProduct:product];

}

@end
</code></pre><br>IAPHelper.h:<br><pre><code>    #import &lt;StoreKit/StoreKit.h&gt;


UIKIT_EXTERN NSString *const IAPHelperProductPurchasedNotification;

typedef void (^RequestProductsCompletionHandler)(BOOL success, NSArray * products);

@interface IAPHelper : NSObject

- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers;
- (void)requestProductsWithCompletionHandler:(RequestProductsCompletionHandler)completionHandler;
- (void)buyProduct:(SKProduct *)product;
- (BOOL)productPurchased:(NSString *)productIdentifier;
- (void)restoreCompletedTransactions;
@property (weak, nonatomic) IBOutlet UIImageView *PokeABowlAd;

@end
</code></pre><br>IAPHelper.m:<br><pre><code>    #define SHOW_ADS_KEY @&#34;Show Ads Key&#34;

// 1
#import &#34;IAPHelper.h&#34;
#import &lt;StoreKit/StoreKit.h&gt;

NSString *const IAPHelperProductPurchasedNotification = @&#34;IAPHelperProductPurchasedNotification&#34;;

// 2
@interface IAPHelper () &lt;SKProductsRequestDelegate, SKPaymentTransactionObserver&gt;
@end

// 3
@implementation IAPHelper {
SKProductsRequest * _productsRequest;
RequestProductsCompletionHandler _completionHandler;

NSSet * _productIdentifiers;
NSMutableSet * _purchasedProductIdentifiers;
}




- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers {

if ((self = )) {

    // Store product identifiers
    _productIdentifiers = productIdentifiers;

    // Check for previously purchased products
    _purchasedProductIdentifiers = ;
    for (NSString * productIdentifier in _productIdentifiers) {
      BOOL productPurchased = [   boolForKey:productIdentifier];
      if (productPurchased) {
            ;
            NSLog(@&#34;Previously purchased: %@&#34;, productIdentifier);
            // NEW CODE
            if (){
                [ setObject: @&#34;No&#34; forKey:SHOW_ADS_KEY];
                [ synchronize];
            }
            // NEW CODE ^^

      } else {
            NSLog(@&#34;Not purchased: %@&#34;, productIdentifier);
      }
    }

    // Add self as transaction observer
    [ addTransactionObserver:self];
}
return self;
}


- (void)requestProductsWithCompletionHandler:(RequestProductsCompletionHandler)completionHandler {


// 1
_completionHandler = ;

// 2
_productsRequest = [ initWithProductIdentifiers:_productIdentifiers];
_productsRequest.delegate = self;
;

}

- (BOOL)productPurchased:(NSString *)productIdentifier {
return ;
}

- (void)buyProduct:(SKProduct *)product {

NSLog(@&#34;Buying %@...&#34;, product.productIdentifier);

SKPayment * payment = ;
[ addPayment:payment];

}

#pragma mark - SKProductsRequestDelegate

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

NSLog(@&#34;Loaded list of products...&#34;);
_productsRequest = nil;

NSArray * skProducts = response.products;
for (SKProduct * skProduct in skProducts) {
    NSLog(@&#34;Found product: %@ %@ %0.2f&#34;,
          skProduct.productIdentifier,
          skProduct.localizedTitle,
          skProduct.price.floatValue);
}

_completionHandler(YES, skProducts);
_completionHandler = nil;

}

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {

NSLog(@&#34;Failed to load list of products.&#34;);
_productsRequest = nil;

_completionHandler(NO, nil);
_completionHandler = nil;

}

#pragma mark SKPaymentTransactionOBserver

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction * transaction in transactions) {
    switch (transaction.transactionState)
    {
      case SKPaymentTransactionStatePurchased:
            ;
            break;
      case SKPaymentTransactionStateFailed:
            ;
            break;
      case SKPaymentTransactionStateRestored:
            ;
      default:
            break;
    }
};
}

- (void)completeTransaction:(SKPaymentTransaction *)transaction {
NSLog(@&#34;completeTransaction...&#34;);

;
[ finishTransaction:transaction];
}

- (void)restoreTransaction:(SKPaymentTransaction *)transaction {
NSLog(@&#34;restoreTransaction...&#34;);

;
[ finishTransaction:transaction];
}

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

NSLog(@&#34;failedTransaction...&#34;);
if (transaction.error.code != SKErrorPaymentCancelled)
{
    NSLog(@&#34;Transaction error: %@&#34;, transaction.error.localizedDescription);
}

[ finishTransaction: transaction];
}

- (void)provideContentForProductIdentifier:(NSString *)productIdentifier {

;
[ setBool:YES forKey:productIdentifier];
[ synchronize];
[ postNotificationName:IAPHelperProductPurchasedNotification object:productIdentifier userInfo:nil];

}

- (void)restoreCompletedTransactions {
[ restoreCompletedTransactions];
}

@end
</code></pre><br>RageIAPHelper.h<br><pre><code>    #import &#34;IAPHelper.h&#34;

@interface RageIAPHelper : IAPHelper

+ (RageIAPHelper *)sharedInstance;

@end
</code></pre><br>RageIAPHelper.m<br><pre><code>    #import &#34;RageIAPHelper.h&#34;
#import &#34;ViewController.h&#34;

@implementation RageIAPHelper

+ (RageIAPHelper *)sharedInstance {
static dispatch_once_t once;
static RageIAPHelper * sharedInstance;
dispatch_once(&amp;once, ^{
    NSSet * productIdentifiers = [NSSet setWithObjects:
                                  @“com.GPS.iapra&#34;,
                                  @&#34;com.GPS.iapb”,
                                  nil];
    sharedInstance = [ initWithProductIdentifiers:productIdentifiers];
});
return sharedInstance;
}

@end
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p>所以我认为正在发生的事情是它直到<code>initWithProductIdentifers</code> 才识别您的购买。正在调用 IAP.m 中的方法(仅在加载应用程序时发生)。<br><br>所以在 IAP.m 中尝试修改:<br><pre><code>- (void)completeTransaction:(SKPaymentTransaction *)transaction {
NSLog(@&#34;completeTransaction...&#34;);

;
[ finishTransaction:transaction];
}
</code></pre><br>到:<br><pre><code>- (void)completeTransaction:(SKPaymentTransaction *)transaction {
NSLog(@&#34;completeTransaction...&#34;);

;

      // NEW CODE
            if (){
                [ setObject: @&#34;No&#34; forKey:SHOW_ADS_KEY];
                [ synchronize];
            }
      // NEW CODE ^^

[ finishTransaction:transaction];
}
</code></pre><br>另外,我认为您的 viewWillAppear 没有被调用的原因是因为您的 Storyboard中似乎有两个 NavigationController。尝试删除第二个(VC 和 MasterVC 之间的那个)。如果您同时执行这两项操作,则应该可以正常工作。</p>
                                   
                                                <p style="font-size: 20px;">关于ios - 购买应用内购买后保存更改,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/31975790/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/31975790/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 购买应用内购买后保存更改