↑クリックして拡大
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大

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

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)を動作させるのが一番わかりやすいのでオススメです! 何かこの記事がお役にたてていれば感謝です。

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

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

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


2021-05-14 14:21:41

WatchOSのwatchconnectivityのFiletransferの落とし穴。と、避け方。

AppleWatch 実機だと成功するんだけど、シュミレーターだと失敗するという、、、 昔作成してた時は成功してたのになーと思って調べると、どうやら昔は成功してたみたい。watchOS6以降は...

2021-05-06 14:04:37

LINEのアニメーションスタンプ制作の落とし穴、、、失敗談

ゴールデンウィークにLINEスタンプを作成してみました。 作り切って申請も通したんですが、意図したアニメーションと違う、、、、 LINEクリエーターの画面だと、アニメーションのプレビュー...

2021-05-01 18:05:35

久しぶりのAdmobをobjective-cに実装。コンパイルエラーだらけ。バーミッション不具合でエミュレータにインスコできない。

忘れないようにメモ エミュレータにアプリをインストールする際にパーミッション系のエラーがでた時、また、iphone実機にインストールする際にも権限系のエラーが出る場合。 ターゲット→ex...
このエントリーをはてなブックマークに追加
右側のFacebookのLikeをクリック頂けると記事更新の際に通知されますので宜しければご利用下さい!