我正在为我的应用程序开发订阅系统,花了几天时间。但是当我正在努力工作时,它会产生更多问题。 有时,当点击购买订阅时应用程序崩溃。
此外,我遇到的问题是不知道何时停止请等待....警告。我需要将代码放入:
case .Purchasing:
self.alert_show()
break
但是我不知道在哪里结束它,我需要知道从加载iTunes的警报时的信息,而不是停止请稍候.... 警报。
现在我遇到的最大问题是当我点击购买按钮时有时会崩溃。
第一次启动应用并点击购买订阅时会发生崩溃。 以下是购买订阅的代码:
@IBAction func buy_sub(sender: AnyObject) {
let payment:SKPayment = SKPayment(product: product)
SKPaymentQueue.defaultQueue().addPayment(payment)
}
这是我得到的错误。
致命错误:在展开“可选”值时意外发现nil ..
我想与您分享我订阅的源代码。如果您有任何建议要添加,或纠正或纠正我遇到的问题,那就太棒了。
以下是订阅视图的完整源代码:
class SubscriptionViewController: UIViewController ,SKPaymentTransactionObserver, SKProductsRequestDelegate {
//var productID = ""
var product: SKProduct!
@IBOutlet var buy_trial_button: UIButton!
override func viewDidAppear(animated: Bool) {
if(SKPaymentQueue.canMakePayments()) {
} else {
buy_trial_button.enabled = false
message_alert("Please enable IAPS to continue(Credit card information required in your iTunes account).")
}
//validateReceipt()
let keystore = NSUbiquitousKeyValueStore.defaultStore()
if keystore.objectForKey("expiration_date") != nil{
let expiration: AnyObject? = keystore.objectForKey("expiration_date")
let today = NSDate()
let expiredate = expiration as! NSDate
print("expiredate is %@",expiredate,today)
// var date1 = NSDate()
// var date2 = NSDate()
if(today.compare(expiredate) == NSComparisonResult.OrderedDescending){
print("today is later than expiredate")
validateReceipt()
print("Validating")
}else if(today.compare(expiredate) == NSComparisonResult.OrderedAscending){
print("today is earlier than expiredate")
self.performSegueWithIdentifier("subscriptionPassed", sender: self)
}
}else{
print("First time launch")
}
}
override func viewDidLoad() {
super.viewDidLoad()
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
self.getProductInfo()
//SKPaymentQueue.defaultQueue().addTransactionObserver(self)
//self.getProductInfo()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillDisappear(animated: Bool) {
}
@IBAction func private_policy(sender: AnyObject) {
let openLink = NSURL(string : "http://arsutech.com/private_policy.php")
UIApplication.sharedApplication().openURL(openLink!)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "subscriptionPassed")
{
}
}
func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse){
let products = response.products
if products.count != 0
{
product = products[0] as SKProduct
print(product.localizedTitle + "\n" + product.localizedDescription)
}
}
func getProductInfo(){
if (SKPaymentQueue.canMakePayments()){
let productID:NSSet = NSSet(object: "com.sxxxxxxxxxxxxxxxxx")
let request:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>)
request.delegate = self
request.start()
}
}
@IBAction func buy_sub(sender: AnyObject) {
let payment:SKPayment = SKPayment(product: product)
SKPaymentQueue.defaultQueue().addPayment(payment)
}
@IBAction func buy_pro(sender: AnyObject) {
let openLink = NSURL(string : "https://itunes.apple.com/us/app/home-workouts-exercises-mma/id1060747118?mt=8")
UIApplication.sharedApplication().openURL(openLink!)
}
@IBAction func exit(sender: AnyObject) {
exit(0)
}
func validateReceipt(){
alert_show()
let mainBundle = NSBundle.mainBundle() as NSBundle;
let receiptUrl = mainBundle.appStoreReceiptURL;
let isPresent = receiptUrl?.checkResourceIsReachableAndReturnError(NSErrorPointer());
if(isPresent == true){
let data = NSData(contentsOfURL: receiptUrl! );
// Create the JSON object that describes the request
let requestContents = NSMutableDictionary();
//let encodeddata = data!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions());
let encodeddata = data!.base64EncodedString();
//print("encodeddata = \(encodeddata)");
requestContents.setObject(encodeddata, forKey: "receipt-data");
requestContents.setObject("c40f23af1aa44e159aezzzzzzzzzzzzzz", forKey: "password");
var requestData : NSData?
do{
requestData = try NSJSONSerialization.dataWithJSONObject(requestContents, options: NSJSONWritingOptions());
}catch{
// NSLog("Error in json data creation at verifyPaymentReceipt");
}
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
let file = "\(documentsPath)/requestData"
if(NSFileManager.defaultManager().createFileAtPath(file, contents: data, attributes: nil)){
NSLog("File %@ ",file);
}
else{
//NSLog("error File %@ ",file);
}
if(requestData != nil){
//let strRequestData = NSString(data: requestData!, encoding: NSUTF8StringEncoding);
//print(" strRequestData = \(strRequestData)");
// Create a POST request with the receipt data.
//https://buy.itunes.apple.com/verifyReceipt
//https://sandbox.itunes.apple.com/verifyReceipt
let storeURL = NSURL(string: "https://sandbox.itunes.apple.com/verifyReceipt");
let storeRequest = NSMutableURLRequest(URL: storeURL!);
storeRequest.HTTPMethod = "POST";
storeRequest.HTTPBody = requestData;
// Make a connection to the iTunes Store on a background queue.
let queue = NSOperationQueue();
NSURLConnection.sendAsynchronousRequest(storeRequest, queue: queue, completionHandler: { (response : NSURLResponse?, data : NSData?, error : NSError?) -> Void in
if(error != nil){
//Handle Error
}
else{
let d = NSString(data: data!, encoding: NSUTF8StringEncoding);
// NSLog("DATA:%@", d!);
let dataA = d!.dataUsingEncoding(NSUTF8StringEncoding)
var jsonResponseInternal: NSMutableDictionary?
do{
jsonResponseInternal = try NSJSONSerialization.JSONObjectWithData(dataA!,options: NSJSONReadingOptions.AllowFragments) as? NSMutableDictionary;
//print(jsonResponseInternal);
}catch{
// NSLog("Parsing issue : verifyPaymentReceipt");
}
var jsonResponse: NSMutableDictionary?
do{
jsonResponse = try NSJSONSerialization.JSONObjectWithData(data!,
options: NSJSONReadingOptions.AllowFragments) as? NSMutableDictionary;
//print(jsonResponse);
}catch{
// NSLog("Parsing issue : verifyPaymentReceipt");
}
if(jsonResponse != nil){
if(jsonResponse != nil){
//NSLog("Expiration Date: %@", jsonResponse!);
//print("Passed")
/*
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "Purchase")
NSUserDefaults.standardUserDefaults().synchronize()
*/
//self.performSegueWithIdentifier("subscriptionPassed", sender: self)
if jsonResponse!["status"] as? Int == 0 {
//print("Sucessfully returned internal receipt data")
if let receiptInfo: NSArray = jsonResponse!["latest_receipt_info"] as? NSArray {
let lastReceipt = receiptInfo.lastObject as! NSDictionary
var trial_period: Bool = false
// Get last receipt
//print("LAST RECEIPT INFORMATION \n",lastReceipt)
print("Last from internal memory",lastReceipt["original_transaction_id"])
//var is_trial = lastReceipt["is_trial_period"] as! Bool
//var date_bought =
//var date_expires =
// Format date
//print(is_trial)
// Format date
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss VV"
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
// Get Expiry date as NSDate
let subscriptionExpirationDate: NSDate = formatter.dateFromString(lastReceipt["expires_date"] as! String) as NSDate!
print("\n - DATE SUBSCRIPTION EXPIRES = \(subscriptionExpirationDate)")
let currentDateTime = NSDate()
print(currentDateTime)
if var is_trial:Bool = false{
if(lastReceipt["is_trial_period"] as? String == "Optional(\"true\")"){
is_trial = true
trial_period = is_trial
}else if(lastReceipt["is_trial_period"] as? String == "Optional(\"false\")"){
is_trial = false
trial_period = is_trial
}
}
if (subscriptionExpirationDate.compare(currentDateTime) == NSComparisonResult.OrderedDescending) {
self.alrt_close()
print("Pass");
print("The trial period is \(trial_period)")
let keystore = NSUbiquitousKeyValueStore.defaultStore()
keystore.setObject(subscriptionExpirationDate,forKey:"expiration_date")
keystore.synchronize()
self.performSegueWithIdentifier("subscriptionPassed", sender: self)
} else if (subscriptionExpirationDate.compare(currentDateTime) == NSComparisonResult.OrderedAscending) {
print("Not Pass");
print("Subscription expired")
self.alrt_close()
//self.message_alert("Subscription expired")
}
}
}
}
}
}
});
}
}
}
func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction:AnyObject in transactions {
if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction{
switch trans.transactionState {
case .Purchasing:
//self.alrt_close()
break
case .Deferred:
self.alert_show()
break
case .Purchased:
alrt_close()
self.validateReceipt()
//self.setExpirationDate()
SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
//dismissViewControllerAnimated(false, completion: nil)
break
case .Failed:
SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
print("Not called Expired")
message_alert("Error while purchasing!")
break
case .Restored:
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
print("Restored")
break
default:
break
}
}
}
}
//Alrt
func message_alert(let message_A:String){
let alert = UIAlertController(title: "", message: "\(message_A)", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
func alert_show(){
let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .Alert)
alert.view.tintColor = UIColor.blackColor()
let loadingIndicator: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRectMake(10, 5, 50, 50)) as UIActivityIndicatorView
loadingIndicator.hidesWhenStopped = true
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
presentViewController(alert, animated: true, completion: nil)
}
func alrt_close(){
self.dismissViewControllerAnimated(false, completion: nil)
}
}