在 Amazons TransferManager 和 BFTask 之后添加 SKPaymentQueue addTransactionObserver 问题

SKPaymentQueue addTransactionObserver issue when it is added after Amazons TransferManager and a BFTask

我几乎按照 Ray Wenderlich 的例子进行应用内购买。这包括我首先从服务器获取我的产品信息。就我而言,我使用 Amazon Web Services。

我遇到的问题是 [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; 不工作,这意味着 - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions 没有被调用。

[[SKPaymentQueue defaultQueue] addTransactionObserver:self];_productIDCompletionHandler 块中被调用。

我已将其缩小为以下代码。只要我在 continueWithExecutor 之前调用 [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; ,观察者就会工作。如果我在 BFTask 块内或之后调用 addTransactionObserver,则不会调用 updatedTransactions 方法。

-(void)getProductidsWithCompletionHandler:(AWSAccessProductIDsCompletionHandler)completionHandler {

_productIDCompletionHandler = [completionHandler copy];

AWSS3TransferManager *transferManager = [AWSS3TransferManager defaultS3TransferManager];

// Construct the NSURL for the download location.
NSString *downloadingFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"aws_downloadedproductidfile"];
NSURL *downloadingFileURL = [NSURL fileURLWithPath:downloadingFilePath];

// Construct the download request.
AWSS3TransferManagerDownloadRequest *downloadRequest = [AWSS3TransferManagerDownloadRequest new];

downloadRequest.bucket = [self bucketStringForType:WB_com_test];
downloadRequest.key = [NSString stringWithFormat:@"%@%@",COM_PRODUCTIDS_FILEPATH,COM_PRODUCTIDS_FILENAME];
downloadRequest.downloadingFileURL = downloadingFileURL;

[[transferManager download:downloadRequest] continueWithExecutor:[BFExecutor mainThreadExecutor]
                                                       withBlock:^id(BFTask *task) {
                                                           if (task.error){
                                                               NSLog(@"Error: %@", task.error);
                                                               _productIDCompletionHandler(NO,nil);
                                                               _productIDCompletionHandler = nil;
                                                           }

                                                           if (task.result) {
                                                               NSLog(@"Success: ");

                                                               AWSS3TransferManagerDownloadOutput *output = task.result;
                                                               NSURL *url = (NSURL *)output.body;
                                                               NSArray *products = [NSArray arrayWithContentsOfURL:url];
                                                               DDLogVerbose(@"Success Result Count: %lu", (unsigned long)[products count]);

                                                               if (products)
                                                               {
                                                                   _productIDCompletionHandler( YES, products);
                                                               } else
                                                               {
                                                                   _productIDCompletionHandler( NO, nil);
                                                               }
                                                               _productIDCompletionHandler = nil;
                                                           }
                                                           return nil;
                                                       }];

}

当上面的 _productIDCompletionHandler 处理程序 returns 在主线程上时,这不是问题,但不知何故线程是 "dirty".

编辑已添加更多信息

我的应用程序内购买 class 调用我的 AWS class 以获取包含我所有产品的文件。在让 Apples observer 开始之前,我需要根据存储在 AWS 上的内容构建我的产品列表。奇怪的是,正如我在上面指出的那样,如果我在调用 getProductidsWithCompletionHandler 之前设置观察者,那么它就可以工作。目前所在的位置,什么也没有发生。

if (!awsAccess) {
awsAccess = [AWSAccess new];
}

[awsAccess getProductidsWithCompletionHandler:^(BOOL success, NSArray *awsProductIDs) {

if (success)
{
    DDLogVerbose(@"Got ProductIDs from AWS...");
    for (NSDictionary *productInfoDict in awsProductIDs)
    {
        IAPProductInfo *info =[[IAPProductInfo alloc] initFromDict:productInfoDict];
        [self addInfo:info forProductIdentifier:info.productIdentifier];
    }

    DDLogVerbose(@"Adding the Apple transaction observer in case there are old purchases.");
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];


} else {
    DDLogVerbose(@"Error getting ProductIDs from AWS...");

}
}];

应用程序内购买 class 包含上述代码,观察者从 Appdelegate 调用,以及当用户通过应用程序发起购买时调用,但始终只有一个观察者作为我的观察者应用内购买 class 是单例。

根据评论更新 2

TestIApurchase.h 实现 SKPaymentTransactionObserver 委托。我创建了一个只有 3 个函数的新测试 class。此 class 专门用于应用程序委托。

我已经在我试用过观察器的地方添加了评论,以及它是否有效。

我检查过"self",它不是零。我还检查了观察者是否在 1 号主线程上被调用,它就是 BFExecutor 在 AWS 代码中的用途。

#import "TestIAPurchase.h"
#import "AWSAccess.h"

@implementation TestIAPurchase


-(void)checkForFailedPurchases {
DDLogVerbose(@"checking for failed purchases by getting all products and waiting to see if Apple replies.");

//Tried it here and it works immediately
//[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

[self loadProductsWithCompletionHandler:^(BOOL success, NSError *error) {
    DDLogVerbose(@"checking for failed purchases Request for products has returned from AWS...");

    if (!success) {
        DDLogVerbose(@"checking for failed purchases Request For Products Failed");

    } else
    {
        DDLogVerbose(@"checking for failed purchases Request For Products was a success...");
        //Tried it here and it does not work if I go and get the AWS information
        //[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    }
}];

}

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
 DDLogVerbose(@"paymentQueue - updatedTransaction...");
for (SKPaymentTransaction * transaction in transactions) {
    switch (transaction.transactionState)
    {
        case SKPaymentTransactionStatePurchased:
            DDLogVerbose(@"SKPaymentTransactionStatePurchased");
            break;
        case SKPaymentTransactionStateFailed:
            DDLogVerbose(@"SKPaymentTransactionStateFailed");
            break;
        case SKPaymentTransactionStateRestored:
            DDLogVerbose(@"SKPaymentTransactionStateRestored");
            break;
        case SKPaymentTransactionStateDeferred:
            DDLogVerbose(@"SKPaymentTransactionStateDeferred");
            break;

        case SKPaymentTransactionStatePurchasing:
            DDLogVerbose(@"SKPaymentTransactionStatePurchasing");
            break;

        default:
            break;
    }
};

}


- (void)loadProductsWithCompletionHandler:(void (^)(BOOL success, NSError * error))productCompletionHandler
{
 DDLogVerbose(@"loadProductsWithCompletionHandler - by getting them from AWS.");


AWSAccess * awsAccess = [AWSAccess new];

//Tried it here and it works immediately
//[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

[awsAccess getProductidsWithCompletionHandler:^(BOOL success, NSArray *awsProductIDs) {


    if (success)
    {
        DDLogVerbose(@"Adding the Apple transaction observer in case there are old purchases.");
        //Trying it here and it does not work
        //[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

        if (productCompletionHandler) {
            productCompletionHandler(TRUE, nil);
        }

    } else {
        DDLogVerbose(@"Error getting ProductIDs from AWS...");
        if (productCompletionHandler) {
            productCompletionHandler(FALSE, nil);
        }
    }
 }];
}
@end

看来我发现了问题。跟AWS没关系,只是碰巧AWS和我的测试有关系。

基本上,当我在应用程序委托中使用上述代码时,Facebook 的代码也在应用程序委托中使用 [FBSDKAppEvents activateApp]; 启动。 Facebook 也听取了同一个观察者的意见。如果我使用 AWS 代码,这将有足够的时间让 Facebook 成为观察员并收到苹果的回复。然后我也注册为观察员,但没有收到 Apple 的回复,我认为这是因为 Apple 刚刚发送了一个。