gpt4 book ai didi

iphone - 如何下载应用内托管内容?

转载 作者:IT王子 更新时间:2023-10-29 08:03:03 28 4
gpt4 key购买 nike

我关注了http://www.raywenderlich.com/21081/introduction-to-in-app-purchases-in-ios-6-tutorial设置 Apple 托管的应用内购买。它列出了产品。当我想从 Apple 下载产品时,我会这样做

-(void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction * transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
{
[[SKPaymentQueue defaultQueue] startDownloads:transaction.downloads];

....

}

-(void) paymentQueue:(SKPaymentQueue *)queue updatedDownloads:(NSArray *)downloads
{
NSLog(@"paymentQues");

for (SKDownload *download in downloads)
{
switch (download.downloadState)
{
case SKDownloadStateActive:
{
NSLog(@"%f", download.progress); break;
}
...

}

-(void) paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions
{

}

我在 updatedTransactions 中开始下载,然后 updatedDownloads 由 Apple 使用 downloadState == Active 调用。然后接下来,Apple 调用 removedTransaction 而没有真正开始下载。下载进度始终为 0%,并且永远不会使用 downloadState == Finished 调用 updatedDownloads。

我不知道为什么我的下载从未开始,以及为什么我的交易在下载完成之前就被删除了。有人有工作样本吗?

最佳答案

问题是我忘了明确关闭交易。作为引用,我的完整代码如下。它还有其他功能,例如在下载时显示进度条,但它 100% 有效。不用担心 Utility.h,它只是定义了一些宏,例如 SAFE_RELEASE_VIEW。

本质上,我通过定义购买和下载两种方法来扩展 raywenderlich 中的示例。

密切关注更新的下载。下载完成后,我将内容复制到用户的文档目录中。当你从 Apple 下载时,你的目录是这样的:

  • >
    • ContentInfo.plist
      • 内容
        • 您的文件

Apple 只为您提供下载文件夹的路径。您使用路径读取 ContentInfo.plist。在我的应用程序中,我在 ContentInfo.plist 中有一个属性“Files”,它在 Contents 文件夹中列出了我的文件。然后我将文件复制到 Documents 文件夹。如果您不这样做,您必须猜测您的 Contents 文件夹中有哪些文件,或者您只需复制其中的所有内容。

这是 SmallChess (http://www.smallchess.com) 的实际应用内购买代码。

#import <StoreKit/StoreKit.h>
#import "MBProgressHUD/MBProgressHUD.h"
#import "Others/Utility.h"
#import "Store/OnlineStore.h"

NSString *const ProductPurchasedNotification = @"ProductPurchasedNotification";

@implementation StoreTransaction
@synthesize productID, payment;
@end

@interface OnlineStore () <SKProductsRequestDelegate, SKPaymentTransactionObserver, MBProgressHUDDelegate>
@end

@implementation OnlineStore
{
NSSet *_productIDs;
MBProgressHUD *_progress;
NSMutableSet * _purchasedIDs;
SKProductsRequest * _productsRequest;
RequestProductsCompletionHandler _completionHandler;
}

-(id) init
{
if ([SKPaymentQueue canMakePayments] && (self = [super init]))
{
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}

return self;
}

#pragma mark MBProgressHUDDelegate

-(void) hudWasHidden:(MBProgressHUD *)hud
{
NSAssert(_progress, @"ddd");

[_progress removeFromSuperview];

SAFE_RELEASE_VIEW(_progress);
}

#pragma end

#pragma mark SKProductsRequestDelegate

-(void) request:(NSSet *)productIDs handler:(RequestProductsCompletionHandler)handler
{
_completionHandler = [handler copy];

_productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIDs];
_productsRequest.delegate = self;
[_productsRequest start];
}

-(void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
_productsRequest = nil;
_completionHandler(YES, response.products);
_completionHandler = nil;
}

-(void) request:(SKRequest *)request didFailWithError:(NSError *)error
{
NSLog(@"Failed to load list of products.");
_productsRequest = nil;

_completionHandler(NO, nil);
_completionHandler = nil;
}

#pragma end

#pragma mark Transaction

-(void) provideContentForProduct:(SKPaymentTransaction *)payment productID:(NSString *)productID
{
[_purchasedIDs addObject:productID];

[[NSUserDefaults standardUserDefaults] setBool:YES forKey:productID];
[[NSUserDefaults standardUserDefaults] synchronize];

StoreTransaction *transaction = [[StoreTransaction alloc] init];

[transaction setPayment:payment];
[transaction setProductID:productID];

[[NSNotificationCenter defaultCenter] postNotificationName:ProductPurchasedNotification object:transaction userInfo:nil];
}

-(void) completeTransaction:(SKPaymentTransaction *)transaction
{
#ifdef DEBUG
NSLog(@"completeTransaction");
#endif

[self provideContentForProduct:transaction productID:transaction.payment.productIdentifier];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

-(void) restoreTransaction:(SKPaymentTransaction *)transaction
{
#ifdef DEBUG
NSLog(@"restoreTransaction");
#endif

[self provideContentForProduct:transaction productID:transaction.originalTransaction.payment.productIdentifier];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

-(void) failedTransaction:(SKPaymentTransaction *)transaction
{
#ifdef DEBUG
NSLog(@"failedTransaction");
#endif

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

[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}

-(void) restoreCompletedTransactions
{
#ifdef DEBUG
NSLog(@"restoreCompletedTransactions");
#endif

[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}

#pragma end

#pragma mark Buy & Download

-(BOOL) purchased:(NSString *)productID
{
return [_purchasedIDs containsObject:productID];
}

-(void) buy:(SKProduct *)product
{
SKPayment * payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}

-(void) download:(StoreTransaction *)transaction
{
NSAssert(transaction.payment.transactionState == SKPaymentTransactionStatePurchased ||
transaction.payment.transactionState == SKPaymentTransactionStateRestored, @"The payment transaction must be completed");

if ([transaction.payment.downloads count])
{
[[SKPaymentQueue defaultQueue] startDownloads:transaction.payment.downloads];
}
}

#pragma end

#pragma mark SKPaymentTransactionObserver

-(void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
NSLog(@"RestoreCompletedTransactions");
}

-(void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction * transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
{
#ifdef DEBUG
NSLog(@"SKPaymentTransactionStatePurchased");
#endif

[[SKPaymentQueue defaultQueue] startDownloads:transaction.downloads];
break;
}

case SKPaymentTransactionStateFailed:
{
NSLog(@"Failed");
[self failedTransaction:transaction];
break;
}

case SKPaymentTransactionStateRestored:
{

NSLog(@"Restored");
[self restoreTransaction:transaction]; break;
}

case SKPaymentTransactionStatePurchasing:
{
#ifdef DEBUG
NSLog(@"SKPaymentTransactionStatePurchasing");
#endif

break;
}
}
}
}

-(void) paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
{
#ifdef DEBUG
NSLog(@"restoreCompletedTransactionsFailedWithError");
#endif
}

-(void) paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions
{
#ifdef DEBUG
NSLog(@"removedTransactions");
#endif
}

-(void) paymentQueue:(SKPaymentQueue *)queue updatedDownloads:(NSArray *)downloads
{
for (SKDownload *download in downloads)
{
switch (download.downloadState)
{
case SKDownloadStateActive:
{
#ifdef DEBUG
NSLog(@"%f", download.progress);
NSLog(@"%f remaining", download.timeRemaining);
#endif

if (download.progress == 0.0 && !_progress)
{
#define WAIT_TOO_LONG_SECONDS 60
#define TOO_LARGE_DOWNLOAD_BYTES 4194304

const BOOL instantDownload = (download.timeRemaining != SKDownloadTimeRemainingUnknown && download.timeRemaining < WAIT_TOO_LONG_SECONDS) ||
(download.contentLength < TOO_LARGE_DOWNLOAD_BYTES);

if (instantDownload)
{
UIView *window= [[UIApplication sharedApplication] keyWindow];

_progress = [[MBProgressHUD alloc] initWithView:[[UIApplication sharedApplication] keyWindow]];
[window addSubview:_progress];

[_progress show:YES];
[_progress setDelegate:self];
[_progress setDimBackground:YES];
[_progress setLabelText:@"Downloading"];
[_progress setMode:MBProgressHUDModeAnnularDeterminate];
}
else
{
NSLog(@"Implement me!");
}
}

[_progress setProgress:download.progress];

break;
}

case SKDownloadStateCancelled: { break; }
case SKDownloadStateFailed:
{
[Utility showAlert:@"Download Failed"
message:@"Failed to download. Please retry later"
cancelTitle:@"OK"
otherTitle:nil
delegate:nil];
break;
}

case SKDownloadStateFinished:
{
NSString *source = [download.contentURL relativePath];
NSDictionary *dict = [[NSMutableDictionary alloc] initWithContentsOfFile:[source stringByAppendingPathComponent:@"ContentInfo.plist"]];

if (![dict objectForKey:@"Files"])
{
[[SKPaymentQueue defaultQueue] finishTransaction:download.transaction];
return;
}

NSAssert([dict objectForKey:@"Files"], @"The Files property must be valid");

for (NSString *file in [dict objectForKey:@"Files"])
{
NSString *content = [[source stringByAppendingPathComponent:@"Contents"] stringByAppendingPathComponent:file];

NSAssert([Utility isFileExist:content], @"Content path must be valid");

// Copy the content to the Documents folder, don't bother with creating a directory for it
DEFINE_BOOL(succeed, [Utility copy:content dst:[[Utility getDocPath] stringByAppendingPathComponent:file]]);

NSAssert(succeed, @"Failed to copy the content");

#ifdef DEBUG
NSLog(@"Copied %@ to %@", content, [[Utility getDocPath] stringByAppendingPathComponent:file]);
#endif
}

if (download.transaction.transactionState == SKPaymentTransactionStatePurchased && _progress)
{
[Utility showAlert:@"Purchased Complete"
message:@"Your purchase has been completed. Please refer to the FAQ if you have any questions"
cancelTitle:@"OK"
otherTitle:nil
delegate:nil];
}

[_progress setDimBackground:NO];
[_progress hide:YES];

[[SKPaymentQueue defaultQueue] finishTransaction:download.transaction];
break;
}

case SKDownloadStatePaused:
{
#ifdef DEBUG
NSLog(@"SKDownloadStatePaused");
#endif
break;
}

case SKDownloadStateWaiting:
{
#ifdef DEBUG
NSLog(@"SKDownloadStateWaiting");
#endif
break;
}
}
}
}

#pragma end

@end

关于iphone - 如何下载应用内托管内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12994550/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com