기다리십시오. 인앱 구매를 설정 한 것은 이번이 처음이며 최대한 많은 정보를 제공하려고 노력합니다. 다른 사람의 코드로 인터넷을 정리하는 대신, 앱에서 비 갱신 구독을 추가하는 방법에 대해 무한 기술로 수업을 구매하는 것으로 끝 맺었습니다. 그들의 수업은 시대에 뒤떨어져 있으며, "따라 가기"프로젝트 파일이 다운로드되지 않았다는 것을 알게되었습니다. 그래서 많은 연구를했고 이것이 내가 생각 해낸 것입니다 :"앱내 구매를 테스트 할 때"lldb "오류가 발생했습니다.
내가 아이튠즈에서 응용 프로그램 내 구입을 만들어는 인앱 식별자 내하는 .m 코딩의 ID를 일치합니다.
새로운 프로비저닝 프로필을 만들고 인앱 구매를 사용하고 icloud를 사용하여 구매 백엔드를 관리했습니다. 앱으로 돌아 왔을 때 icloud를 사용 설정하고 프로젝트 타겟에서 인앱 구매가 사용 설정되었는지 확인했습니다.
버튼을 추가하고 SKStoreProductViewController를 사용하는 하위 클래스를 만들었습니다. 해당보기 컨트롤러는 다음과 같습니다.
나는 storekit 및 SK 대리자를 가져 왔습니다.
내 홈 뷰에서 Tabbar 버튼을 누르면 인앱보기 컨트롤러로 이동하면 충돌이 발생합니다.
마지막으로 코딩 : InAppViewController.h :
#import <StoreKit/StoreKit.h>
@interface InAppViewController : SKStoreProductViewController
@end
InAppViewController.m :
//
// InAppViewController.m
// Contractor Rich
//
// Created by Joshua Hart on 2/1/15.
// Copyright (c) 2015 Code By Hart. All rights reserved.
//
#import "InAppViewController.h"
#import <StoreKit/StoreKit.h>
@interface InAppViewController()<SKProductsRequestDelegate, SKPaymentTransactionObserver>
@property (weak, nonatomic) IBOutlet UIButton *btnBuyAccess;
@property (weak, nonatomic) IBOutlet UIButton *btnPremiumFeature;
@property (weak, nonatomic) IBOutlet UILabel *lblStatus;
@property (strong, nonatomic) SKProduct *product;
@property (strong, nonatomic) NSUbiquitousKeyValueStore *keyStore;
@property (strong, nonatomic) NSDate *expirationDate;
- (IBAction)btnBuyAccessTouched: (id)sender;
-(void)getProductInfo;
@end
@implementation InAppViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_btnBuyAccess.userInteractionEnabled = NO;
_keyStore = [[NSUbiquitousKeyValueStore alloc] init];
_expirationDate = [_keyStore objectForKey:@"expirationDate"];
NSDate *today = [NSDate date];
if (_expirationDate == nil)
_expirationDate = today;
if (_expirationDate > today) {
_btnPremiumFeature.userInteractionEnabled = YES;
}
else {
_btnBuyAccess.userInteractionEnabled = YES;
[self getProductInfo];
}
}
-(void) getProductInfo{
if ([SKPaymentQueue canMakePayments])
{
NSMutableArray *productIdentifierList = [[NSMutableArray alloc] init];
[productIdentifierList addObject:[NSString stringWithFormat:@"com.joshua.contractorrich.inapp"]];
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithArray:productIdentifierList]];
request.delegate = self;
[request start];
}
}
-(void) productsRequest: (SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSArray *products = response.products;
if (products.count != 0)
{
_product = products[0];
_btnBuyAccess.userInteractionEnabled = YES;
_lblStatus.text = @"Ready for Purchase!";
}else{
_lblStatus.text = @"Product was not Found!";
}
products = response.invalidProductIdentifiers;
for (SKProduct *product in products)
{
NSLog(@"Product not found: %@", product);
}
}
- (IBAction)btnBuyAccessTouched: (id)sender {
SKPayment *payment = [SKPayment paymentWithProduct:_product];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchased:
_btnPremiumFeature.userInteractionEnabled = YES;
_lblStatus.text = @"Purchase Completed!";
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateFailed: NSLog(@"Transaction Failed!");
_lblStatus.text = @"Purchase Failed!";
[[SKPaymentQueue defaultQueue]
finishTransaction:transaction];
default:
break;
}
}
}
-(void) setExpirationDate {
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setMonth:3];
NSDate *expirationDate = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:[NSDate date] options:0];
[_keyStore setObject:expirationDate forKey:@"expirationDate"];
[_keyStore synchronize];
}
-(void) initializeStore {
[_keyStore setObject:nil forKey:@"expirationDate"];
[_keyStore synchronize];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
이 내 처음이 노력을 양해 해 주시기 바랍니다. 어리석은 것처럼 보일지 모르지만 여전히 나를위한 학습 단계입니다. 고맙습니다!
CUICatalog 란 무엇입니까? 그것이 오류 메시지의 소스입니다. – matt
그 아이가 찾을 수없는 이미지는 어딘가에서 두통을 일으켰습니다. 저는 언젠가는 고칠 수 없었던 오류였습니다. 응용 프로그램은 디버거에서 표시되는 tho에도 잘 작동합니다. 인앱 런타임 오류에는 영향을주지 않습니다. –
하지만 그것이 유일한 문제입니다. 그게 문제가 아니라면 어떤 문제가 있습니까? 스크린 샷에 다른 "런타임 오류"가 표시되지 않습니다. – matt