在 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 刚刚发送了一个。
我几乎按照 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 刚刚发送了一个。