Swift転職なら=>【LevTech】
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大

頭痛が減ったので共有です!

rebuild.fmを応援しています!

HOME > AppleWatchをNSFileCoordinatorとKeychainでデータ交換

AppleWatchをNSFileCoordinatorとKeychainでデータ交換

サンプル画像

前回の記事(ナターシャさんのサンプルデモを元に解説)の続きです。今記事はNSUserDefaultではなく、 NSFileCoordinatorとKeychain sharingを利用しての解説です。ナターシャさんのサンプルに関して前記事をご参照ください。

やってみた (NSFileCoordinator)

サンプル画像

NSUserDefaultとほぼ同じでAppGroupを利用します。(※AppGroupはそれぞれ環境に応じて設定してください。詳細は前記事をご確認ください)

↓ アプリ本体のソースです


import UIKit

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let fileCoordinator = NSFileCoordinator()
        let groupURL = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.com.okko.demoAppExtensions")
        let fileURL = groupURL?.URLByAppendingPathComponent("testData.bin")
        fileCoordinator.coordinateWritingItemAtURL(fileURL!, options: nil, error: nil)
            { [unowned self] (newURL) -> Void in
                let saveData = "hogehoge"
                let dataToSave = NSKeyedArchiver.archivedDataWithRootObject(saveData)
                let ret = dataToSave.writeToURL(newURL, atomically: true)
                println(ret);//true
        }>
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

App Groupを設定して指定アプリURLにtestData.binのバイナリデータを書き込んでいます。NSUserDefaultと使い方はほぼ同じです。 使い分けとしてはNSFileCoordinatorはバイナリデータを書き込むので大きなファイルやキャッシュが必要な頻繁にアクセスするファイルを保存する場合に 利用する等、用途に応じてNSUserDefaultと使い分けすると良いのではと思います。(参考サイト:NSUserDefaults、ファイル、データベース、どれで保存するか)

↓ AppleWatch側のソースです


import WatchKit
import Foundation

class InterfaceController: WKInterfaceController {
    
    override func awakeWithContext(context: AnyObject?) {
        super.awakeWithContext(context)
        
        let fileCoordinator = NSFileCoordinator()
        let groupURL = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.com.okko.demoAppExtensions")
        let fileURL = groupURL?.URLByAppendingPathComponent("testData.bin")
        fileCoordinator.coordinateReadingItemAtURL(fileURL!, options: nil, error: nil)
            { [unowned self] (newURL) -> Void in
                if let savedData = NSData(contentsOfURL: newURL) {
                     println(NSKeyedUnarchiver.unarchiveObjectWithData(savedData) as String)//Optional(hogehoge)
                }
        }
    }

    override func willActivate() {
        // This method is called when watch view controller is about to be visible to user
        super.willActivate()
    }

    override func didDeactivate() {
        // This method is called when watch view controller is no longer visible
        super.didDeactivate()
    }
}

受け取り時に上記サンプルではNSKeyedUnarchiverをString型で解凍していますが、 この箇所を画像等それぞれ切り替えてデータを受け取ってください。

(※データがアプリ本体側で変更されたイベントをWatch側で受け止めるにはNSFilePresenterNSOperationQueueを利用します。)

やってみた(Key Chain)

サンプル画像

アプリ端末とAppleWatch間のデータ送受信はBluetooth通信なので解読される可能出てきます。 セキュリティを向上させるためAPP側で暗号、AppleWatch側で複合する為にこのKeychain sharingを利用します。こちはNSUserDefault、NSFileCoordinatorと 違います。ナターシャさんのデモサンプルを触るとわかりやすいのでオススメです。以下、気づいた箇所とソースを抜粋します。

サンプル画像

TargetのCapabilityではAppGroupsを利用しません。代わりにKeychain Sharingを利用します。

↓ App側のソースです



import UIKit
import SharedDataLayer

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let username = "Swift-Salaryman"
        let password = "higegakoi"
        let keychainItem = KeychainItemWrapper(identifier: "SharingViaKeychain", accessGroup: "com.okko.SharingViaKeychain")
        keychainItem.setObject(username, forKey: kSecAttrAccount)
        keychainItem.setObject(password, forKey: kSecValueData)
    }
}

KeychainItemWrapperを利用して暗号化させます


↓ AppleWatch側のソースです


import WatchKit
import SharedDataLayer

class InterfaceController: WKInterfaceController {
    
    override func awakeWithContext(context: AnyObject?) {
        super.awakeWithContext(context)
        
        let keychainItem = KeychainItemWrapper(identifier: "SharingViaKeychain", accessGroup: "com.okko.SharingViaKeychain")
        let passwordData = keychainItem.objectForKey(kSecValueData) as NSData
        let password = NSString(data: passwordData, encoding: NSUTF8StringEncoding)
        let username = keychainItem.objectForKey(kSecAttrAccount) as? String
        println(""\(username):\(password))//Swift-Salaryman:higeganagai
    }
}

KeychainItemWrapperを利用して複合化させます。さて、KeychaninItemWrapperとはなんでしょうか? こちらはAppleから提供されているようでObjective-Cで記載されているライブラリ。 ブリッジヘッダによってObjCとSwiftを共存させます(共存方法はこちらをご参照ください。) ナターシャさんはSharedDataLayer.hを自作されてKeychainItemWrapperを利用されていました。

サンプル画像

このライブラリの説明をすると別の記事になってしまうのでここまでにします。

まとめ

Keychain Sharingの説明はなんだか中途半端で失礼しております、、、。ナターシャさんのデモ(on Github)を動作させるのが一番わかりやすいのでオススメです! 何かこの記事がお役にたてていれば感謝です。

前の記事はこちらからです!

次の記事はこちらからです!

↓こんな記事もありますよ!

NSFileManagerでAPP保存領域のデータ操作

ファイルやディレクトリ作成はなんとなく面倒くさいイメージがありましたが、この記事で少し自分の中で壁が低くなった気がします。 よろしければご利用くださいませ。

UITextViewでテキストを複数行表示する

UITextFieldは一行表示ですが、UITextFieldは複数行を表示することができます。

アップルWatchから親アプリケーションへデータ送信

前回の記事では実機上で親アプリケーションからAppleWatchにイベントを送るのができなかった。 Notificationでできるはずなのですが、動作してくれなかった、、、、、。今回はいったん逆の時計から親アプリへのデータ送信の方法サンプルサイト をQiita様の中の記事でみつけましたので検証してみます。
このエントリーをはてなブックマークに追加
右側のFacebookのLikeをクリック頂けると記事更新の際に通知されますので宜しければご利用下さい!