iOS 内购单例封装详细代码 - Swift 和 Objective-C 实现
以下是一个封装了内购功能的单例类的详细代码,包含 Swift 和 Objective-C 两种语言的实现:
Swift 代码示例
import StoreKit
class IAPManager: NSObject, SKProductsRequestDelegate, SKPaymentTransactionObserver {
typealias ProductsRequestCompletionBlock = (SKProductsRequest, SKProductsResponse) -> Void
typealias BuyProductCompletionBlock = (SKPaymentTransaction) -> Void
var productsRequestCompletionBlock: ProductsRequestCompletionBlock?
var buyProductCompletionBlock: BuyProductCompletionBlock?
static let shared = IAPManager()
private override init() {
super.init()
SKPaymentQueue.default().add(self)
}
func requestProducts(withIdentifiers identifiers: Set<String>, completion: @escaping ProductsRequestCompletionBlock) {
self.productsRequestCompletionBlock = completion
let request = SKProductsRequest(productIdentifiers: identifiers)
request.delegate = self
request.start()
}
func buyProduct(_ product: SKProduct, completion: @escaping BuyProductCompletionBlock) {
self.buyProductCompletionBlock = completion
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(payment)
}
// MARK: - SKProductsRequestDelegate
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
if let completionBlock = productsRequestCompletionBlock {
completionBlock(request, response)
}
productsRequestCompletionBlock = nil
}
// MARK: - SKPaymentTransactionObserver
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch transaction.transactionState {
case .purchasing:
// 正在购买
break
case .purchased:
// 购买成功
if let completionBlock = buyProductCompletionBlock {
completionBlock(transaction)
}
queue.finishTransaction(transaction)
case .failed:
// 购买失败
if let completionBlock = buyProductCompletionBlock {
completionBlock(transaction)
}
queue.finishTransaction(transaction)
case .restored:
// 已经购买过该商品
if let completionBlock = buyProductCompletionBlock {
completionBlock(transaction)
}
queue.finishTransaction(transaction)
default:
break
}
}
}
}
Objective-C 代码示例
#import <StoreKit/StoreKit.h>
@interface IAPManager : NSObject <SKProductsRequestDelegate, SKPaymentTransactionObserver>
typedef void(^IAPProductsRequestCompletionBlock)(SKProductsRequest *request, SKProductsResponse *response);
typedef void(^IAPBuyProductCompletionBlock)(SKPaymentTransaction *transaction);
@property (nonatomic, copy) IAPProductsRequestCompletionBlock productsRequestCompletionBlock;
@property (nonatomic, copy) IAPBuyProductCompletionBlock buyProductCompletionBlock;
+ (instancetype)sharedManager;
- (void)requestProductsWithIdentifiers:(NSSet *)identifiers completion:(IAPProductsRequestCompletionBlock)completion;
- (void)buyProduct:(SKProduct *)product completion:(IAPBuyProductCompletionBlock)completion;
@end
@implementation IAPManager
+ (instancetype)sharedManager {
static IAPManager *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [[self alloc] init];
});
return sharedManager;
}
- (instancetype)init {
self = [super init];
if (self) {
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}
return self;
}
- (void)requestProductsWithIdentifiers:(NSSet *)identifiers completion:(IAPProductsRequestCompletionBlock)completion {
self.productsRequestCompletionBlock = completion;
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:identifiers];
productsRequest.delegate = self;
[productsRequest start];
}
- (void)buyProduct:(SKProduct *)product completion:(IAPBuyProductCompletionBlock)completion {
self.buyProductCompletionBlock = completion;
SKPayment *payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
#pragma mark - SKProductsRequestDelegate
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
if (self.productsRequestCompletionBlock) {
self.productsRequestCompletionBlock(request, response);
}
self.productsRequestCompletionBlock = nil;
}
#pragma mark - SKPaymentTransactionObserver
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions {
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchasing:
// 正在购买
break;
case SKPaymentTransactionStatePurchased:
// 购买成功
if (self.buyProductCompletionBlock) {
self.buyProductCompletionBlock(transaction);
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
// 购买失败
if (self.buyProductCompletionBlock) {
self.buyProductCompletionBlock(transaction);
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
// 已经购买过该商品
if (self.buyProductCompletionBlock) {
self.buyProductCompletionBlock(transaction);
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
default:
break;
}
}
}
@end
使用方法
// 请求商品信息
IAPManager.shared.requestProducts(withIdentifiers: ['com.yourproductid']) { request, response in
if let products = response.products, !products.isEmpty {
let product = products.first!
// 购买商品
IAPManager.shared.buyProduct(product) { transaction in
if transaction.transactionState == .purchased {
// 购买成功
} else if transaction.transactionState == .failed {
// 购买失败
}
}
}
}
// 请求商品信息
[[IAPManager sharedManager] requestProductsWithIdentifiers:[NSSet setWithObject:@'com.yourproductid'] completion:^(SKProductsRequest *request, SKProductsResponse *response) {
NSArray *products = response.products;
if (products.count > 0) {
SKProduct *product = products.firstObject;
// 购买商品
[[IAPManager sharedManager] buyProduct:product completion:^(SKPaymentTransaction *transaction) {
if (transaction.transactionState == SKPaymentTransactionStatePurchased) {
// 购买成功
} else if (transaction.transactionState == SKPaymentTransactionStateFailed) {
// 购买失败
}
}];
}
}];
以上代码封装了内购功能的单例类,提供了请求商品信息和购买商品的方法,并通过回调方式返回购买结果。
注意:
- 记得将
com.yourproductid替换为你的实际商品 ID。 - 在实际使用中,需要根据你的应用逻辑处理不同的购买结果。
- 为了防止重复购买,建议在购买成功后将商品信息存储到用户本地。
- 为了确保用户体验,建议在购买过程中显示加载提示。
- 为了安全起见,建议使用沙盒测试环境进行测试,不要直接使用真实环境进行测试。
希望以上内容能够帮助你更好地理解和使用 iOS 内购功能。
原文地址: https://www.cveoy.top/t/topic/Ei4 著作权归作者所有。请勿转载和采集!