2015年

4月

17日

Apple Watch WatchKit <- iPhone App データ共有する方法(UserDefaults)

AppleWatchとiPhone間でのデータ交換方法について

 

データ交換において3つの方法があります。

NSUserDefaultsを利用する(オーソドックスな共有)
NSFileCoordinatorを利用する(ファイルを共有)
Keychain Sharingを利用する(暗号化して共有)

 

このページは、NSUserDefaults(ファイルを共有)についてまとめています。

 

NSUserDefaultsとは


アプリケーションの設定値など、アプリを停止させてもずっと保持しておきたい情報などはよくありますが、NSUserDefaultsを使うとそうしたデータを簡単に保持できます。

使い方としてはNSUserDefaultsを取得して、取得したNSUserDefaultsに対してデータを保存したり取り出したりすることでデータ保持を行います。

 

まずiPhone WatchKit とデータ共有するには、Bundle Identifier のような識別子によって管理されApp Groupに登録する必要があります。

App Groupとは
iPhoneアプリのデータをApple Watchで見られるようにするには、App Groupを使う必要があります。App Groupは、複数のアプリの間でデータを共有できるようになる新しい機能です。

今までも Keychainの仕組みを使うことでアプリ間のデータ共有はできましたが手続きが面倒だったり機種変更のデータ復元などで問題がありました。

App Groupを使うと、今までと同じNSUserDefaultsなどを利用してデータ共有をすることができます。App Extensionではこの仕組みを使うとアプリとExtension間のデータ受け渡しが楽になります。


App Groupで共有できる範囲
App Groupでは、アプリとアプリの間、アプリとApp Extensionの間でデータ受け渡しをすることができます。

ただし、違う会社からリリースされているアプリの間での情報共有はできません。
App Groupの設定をするためには、同じ Developerからリリースされているアプリである必要があります。

App Groupを使うと、NSUserDefaultsを使った設定情報の共有とNSFileManagerを使ったファイルの共有ができます。

 

補足

Watch Kit AppとiPhone Appのデータは別管理
基本的にWatch Kit AppとiPhone Appがそれぞれ保持するデータ領域は別々に管理されています。したがって、App Groupsの設定を行わずにNSUserDefaultsを使ってみると、Watch Kit Appで保存したデータはWatch Kit Appからしか利用することはできません。逆もしかり。

App Groupsの設定をすれば、Watch Kit AppとiPhone App間でデータ共有が可能になります。


App Group を使った情報共有方法(準備)

App Groupを使うためには、まず iOS Dev Centerで App GroupのGroup IDを登録します。
「group.com.xxxxx.watchlist」というように、Bundle Identifierと同じようにドメイン名などから生成した一意な文字列の先頭に「group」をつけるのが推奨されています。

Dec Centerでの設定が終わったら、共有したいアプリをXcodeで開きます。
ProjectファイルのCapability タブを開き、 App Groupの設定をonにします。
App Groupの機能をonにすると、さきほど iOS Dev Centerで設定した Group IDが表示されるので、チェックボックスをonにします。

すると、プロジェクトにEntitlementファイルが追加されます。
共有をしたいアプリやExtensionのすべてについてこの設定を行ってください。

詳細は、アプリ制作にて示していますので参照願います。



Xcode 6.2 以上(6.3にて制作)

Download Xcode for Free
https://developer.apple.com/xcode/downloads/
6.2からAppleWatch開発環境(watchkit)が入っています。


iOS8.2以上 (iPhone)
8.2にバージョンアップするとアプリ「Apple Watch」が追加されるのですぐわかります。

iPhoneアプリケーション プロジェクトを生成
xcode起動後、「Create a new Xcode project」を選択します。
次にiOS -> Application -> Single View Applicationを選択します。

 

プロダクト名をWatchKitUserDefaultsとします。

Watch Kit Appを追加
Watch Kitを追加します。File -> New -> Target を選択します。


AppleWatch ->WatchKit Appを選択します。


Include Glance、Include Notification Scene は、今回使わないのでチェックを外す。

Finishiをクリックします。

 

Activateをクリックします。

 

App Group の有効化

データを共有したい containing app や Extension は個別に App Group を設定する必要があります。まずは、containing app の設定を行います。

App Group の設定は、ターゲットの Capabilities で行います。containing app のターゲットを選択して、Capabilities タブを選択して下さい。



その中に App Groups というカテゴリがありますので、スイッチを ON にして有効化して下さい。


すると、どの Development Team を対象にするかを選択するダイアログが表示されますので、containing app と Extension をリリースしたい Development Team を選択して Choose をクリックして下さい。


Capabilities の画面に戻ります。App Group のカテゴリ内に、Development Team に対して登録済みの App Group のリストが表示されます。下図では、先程選択した Development Team に App Group が登録されていないため、リストは空になっています。

 

App Group の作成

App Group リストの左下に App Group を追加する + ボタンがありますので、それをクリックします。

 

App Group の識別子を入力するダイアログが表示されます。App Group の識別子は group. で始まる必要があります。group. の後ろは、Bundle Identifier と同じように逆ドメインを指定するようにしましょう。識別子を入力したら OK をクリックします。


例)group.com.xxxxx.watchlist

識別名:watchlist (任意ですからそれぞれ重複しない名前にすれば良いです。)


Capabilities の画面に戻ると、登録済み App Group リストに先程追加した App Group の識別子が追加されているのが確認できます。


追加した App Group を iOS Developer Center で確認してみましょう。Certificates, Identifiers & Profiles のページ内に App Groups という項目があります。App Group を作成したアカウントでログインして App Groups を選択すると、一覧に作成した App Group が追加されているのが確認できます。

 

これで iPhone containing app 側の App Group の設定は完了しました。iPhone App TARGETのExtension にも先程作成した App Group の設定を追加します。

iPhone AppのTARGETとWatch KitのTARGET両方に設定する必要があります。片方にしか設定していないとデータ共有がうまく行われません。

 

Watch Kit TARGETExtension にも先程作成した App Group の設定を追加します。


Action Extensionとは

Action Extension は iOS 8 より利用できるようになった App Extension が提供する機能の一部です。これは、アプリが提供する機能を他のアプリから利用できるようにする Extension で、Extension の中でも割り合い汎用的な機能を備えています。

Action Extension の主な利用用途としては、他のアプリが保持しているデータを独自の形式で表示したり、他のアプリが保持しているデータに対して、ユーザーが編集を行うための独自の UI を提供するといったことが挙げられます。


 

Main.storyboardでUIを作成します。
いつものiOS開発と同じです。Label、TextField、Buttonを貼り付けます。

 

Interface.storyboardでUIを作成します。
いつものiOS開発と同じです。LabelとButtonを貼り付けます。

位置調整はこのままです。

プログラムでの位置調整ができませんのでその点はご注意ください。

 

※Apple WatchにはGlance(ぱっと見る)、Notification(通知)という機能に関するものもありますが、これらについては今回は使用しません。

※今回は「Static Interface」や「Dynaminc Interface」の機能は使用しないので、特にこの部分に関しては特に追加や修正を行う必要はありません。

 

iPhone側のデータの保存ソースコード

ViewController.mに記述します。

#import "ViewController.h"


@interface ViewController ()


// 表示フィールド

@property (weak, nonatomic) IBOutlet UILabel *textLabel;


// 入力テキストフィールド

@property (weak, nonatomic) IBOutlet UITextField *textField;


@end


@implementation ViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    

    // 何かを入力するようにメッセージ表示

    self.textField.text = @"Type Something...";

    

}


// データの保存

- (IBAction)onSaveTap:(id)sender {

    

    // データの保存 App Groups

    NSUserDefaults *defaults = [[NSUserDefaults alloc]  

                    initWithSuiteName:@"group.com.iScene.UserDefaults"];

    // テキストフィールドの文字をキー:userInput 付きでセットする

    [defaults setObject:self.textField.text forKey:@"userInput"];

    // NSUserDefaultsに即時反映させる(即時で無くてもよい場合は不要)

    [defaults synchronize];

    

    self.textLabel.text = self.textField.text;

    

}



- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

 

Watch Extension側のデータ読み込みソースコード

InterfaceController.mに記述します。

#import "InterfaceController.h"



@interface InterfaceController()


@property (weak, nonatomic) IBOutlet WKInterfaceLabel *textLabel;


@end



@implementation InterfaceController


- (void)awakeWithContext:(id)context {

    [super awakeWithContext:context];


}


- (void)willActivate {

    // This method is called when watch view controller is about to be visible to user

    [super willActivate];

}


- (void)didDeactivate {

    // This method is called when watch view controller is no longer visible

    [super didDeactivate];

}


- (IBAction)showUpdate {

    

    // データの読み込み

    // NSUserDefaultsを作成 オブジェクトへのアクセスを共有

    NSUserDefaults *defaults = [[NSUserDefaults alloc]   

                    initWithSuiteName:@"group.com.iScene.UserDefaults"];

    // テキストラベルに表示

    self.textLabel.text = [defaults stringForKey:@"userInput"];

}

@end


  

目 次

 

コメントをお書きください

コメント: 2
  • #1

    Shin12 (日曜日, 09 8月 2015 10:33)

    ちょうどデータのやりとりの方法を探していました。
    情報ありがとうございます。開発の参考にさせていただきます。

  • #2

    luke (日曜日, 09 8月 2015 11:25)

    参考になれば幸いです。