iOSアプリでデータを保存する時の注意

データの参照場所を絶対パスでCoreData等に永続化する作りにしてしまうと、アプリを実行するごとにドキュメントディレクトリの場所が変更されてしまうので次回アプリを立ち上げるとデータを開くことができなくなる。

なのでファイル名のみを保存しておき、以下のようにして取り出す必要がある。

let fname = "demo.png" // ファイル名
let abspath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0].stringByAppendingString(fname) 
let url = NSURL(string: abspath)!
let data = NSData(contentsOfURL: NSURL(string: url))!

アプリ内課金の実装を簡単にするStoreMangerクラスを作った

StoreManager.swfit

import Foundation
import UIKit
import StoreKit

class StoreManager:NSObject ,SKProductsRequestDelegate, SKPaymentTransactionObserver{
    static let sharedInstance = StoreManager()
    var transactionInProgress = false
    var productIDs:Array = [""]
    var productsArray: Array = []
    var selectedProductIndex: Int!
    var restore = false
    var payment:SKPayment!

    func requestProductInfo() {
        if SKPaymentQueue.canMakePayments() {
            let productIdentifiers = NSSet(array: StoreManager.sharedInstance.productIDs)
            let productRequest = SKProductsRequest(productIdentifiers: productIdentifiers as! Set)
            productRequest.delegate = self
            productRequest.start()

        }
        else {
            print("Cannot perform In App Purchases.")
        }
    }

 
    func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
        print("productsRequest")
        if response.products.count != 0 {
            for product in response.products {
                print("validProduct:\(product)")
                StoreManager.sharedInstance.productsArray.append(product)
                self.payment = SKPayment(product: product)
                self.transactionInProgress = true
                SKPaymentQueue.defaultQueue().addPayment(self.payment)
                request.delegate = self
                request.start()
            }
        }
        else {
            print("There are no products.")
        }

        if response.invalidProductIdentifiers.count != 0 {
            print("invalidProductIdnetfiers:\(response.invalidProductIdentifiers.description)")
        }
    }


    func paymentQueue(queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: NSError) {
        print(error.description)
        print("paymentque restore")

    }

    // 購入履歴が確認できた場合
    func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) {
        var restore = false
        print("paymentQueueRestore")

        //すでに商品を購入していたら、復元を行う

        for transaction in queue.transactions {
            print(transaction.payment.productIdentifier)

            if transaction.payment.productIdentifier == "Pro" {
                restore = true

               
            }
        }
  
        if restore == true {
            NSUserDefaults.standardUserDefaults().setBool(true, forKey: "pro")
            let av = UIAlertView(title: "", message: "Restored Successfully", delegate: nil, cancelButtonTitle: "OK")
            av.show()
        }else{
            print("called")
            // failed restore
            let av = UIAlertView(title: "", message: "There is no item to restore", delegate: nil, cancelButtonTitle: "OK")
            av.show()
        }
    }



    func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        print("update Transaction")
    
        for transaction in transactions {
            switch transaction.transactionState {
            case SKPaymentTransactionState.Purchased:
                print("Transaction completed successfully.")
                SKPaymentQueue.defaultQueue().finishTransaction(transaction)
                self.transactionInProgress = false
                NSUserDefaults.standardUserDefaults().setBool(true, forKey: "pro")
                NSUserDefaults.standardUserDefaults().synchronize()

            case SKPaymentTransactionState.Failed:
                print("Transaction Failed");
                SKPaymentQueue.defaultQueue().finishTransaction(transaction)
                self.transactionInProgress = false


            case SKPaymentTransactionState.Purchasing:
                print("purchasing")

            case SKPaymentTransactionState.Restored:
                print("SKPaymentTransactionState.Restored")
                self.transactionInProgress = false
                SKPaymentQueue.defaultQueue().finishTransaction(transaction)
                
            default:
                print("default")
                
            }
        }
    }

    

使い方

購入

StoreManager.sharedInstance.requestProductInfo()

リストア

SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
SKPaymentQueue.defaultQueue().addTransactionObserver(StoreManager.sharedInstance)

コードはGistからもダウンロードできます。

UIColorの値をNSUserDefaultに保存する

UIColorシリアライズすることでNSUserDefaultsに保存することができる。

UIColorをNSUserDefaultsに保存

  let data = NSKeyedArchiver.archivedDataWithRootObject(button.backgroundColor!)

  NSUserDefaults.standardUserDefaults().setObject(data, forKey: "colorscheme")
  NSUserDefaults.standardUserDefaults().synchronize()

UIColorをNSUserDefaultsから取り出す

if let _data:NSData = NSUserDefaults.standardUserDefaults().objectForKey("colorscheme") as? NSData {
    // savedColor: NSUserDefaultsに保存したUIColor  
   if let savedColor  = NSKeyedUnarchiver.unarchiveObjectWithData(_data) as? UIColor {
            
   }
}

[swift] UserAgentを設定する

要件

UIWebViewから来たリクエストのUserAgentを”ios-webview”に変更したい。

Code

func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool { ...
    
    let str = "ios-webview"
    let dic:NSDictionary = ["UserAgent":str]
    NSUserDefaults.standardUserDefaults().registerDefaults(dic)

iOSアプリのUIWebViewから来たかどうかを判定する

detect.js

var isFromUIWebView = (window.navigator.userAgent.indexOf("ios-webview") !== -1);
if (isFromUIWebView === true) {
    console.log("from uiwebview");
}

現在のUIViewControllerを取得する

Code

extension UIApplication {
    class func topViewController(base: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController) -> UIViewController? {
        if let nav = base as? UINavigationController {
            return topViewController(nav.visibleViewController)
        }
        if let tab = base as? UITabBarController {
            if let selected = tab.selectedViewController {
                return topViewController(selected)
            }
        }
        if let presented = base?.presentedViewController {
            return topViewController(presented)
        }
        return base
    }
}

使い方

if let vc  = UIApplication.topViewController()  {
   // write something.
}