cockscomblog?

cockscomb on hatena blog

WatchKitアーキテクチャ概論

来年初めにリリースされるというApple WatchSDKがプレリリースされた。Appleはこれを WatchKit と呼ぶ。Apple Watchで動作するWatchKitアプリは、いったいどのようなアーキテクチャにより駆動されるのか。この興味深い仕組みについて考察する。

WatchKit - Apple Developer

ふたつの予想

Appleウェアラブルデバイスを開発しているという噂が流れていた頃、そのアプリケーションのアーキテクチャについて異なる二つの予想をしていた。

一つは、ウェアラブル端末本体で動作する通常のアプリを作るというパターン。これはAndroid Wearが採用しており、Androidのアプリを作るのとほとんど同じようにウェアラブル端末で動作するアプリを作ることができる。これが採用されると、UIKitの多くのコンポーネントが利用できることになり、柔軟なアプリを作成できる。その反面でウェアラブル端末の少ないバッテリーは大きく消費される恐れがあるし、比較的非力なSoCに最適化する必要がある。加えて、ウェアラブル端末には通常インターネットに接続する機能はなく、コンパニオンとなるスマートフォンから借用することになるが、これを実装するのは面倒な作業になる。

もう一つは、コンパニオンとなるスマートフォンの側にアプリの機能を実装し、その画面をウェアラブル端末に表示するというパターンである。すなわちウェアラブル端末をセカンドスクリーンとして用いることになる。結果としてウェアラブル端末のハードウェア上の機能に束縛されることなくアプリを作ることができる。これはApple TVを利用するAirPlayや、車載端末であるCarPlayアーキテクチャに近いものであろう。ただし、ウェアラブル端末とスマートフォンは現行の技術ではBluetooth Low Energyで接続されることが予想され、画面を逐一転送できるだけの通信速度は出ないだろうと思われる。

これらの二つの予想は、それぞれに利点や問題を持っている。ただAppleの最近の技術的なトレンドを考慮すると、後者の方に分があるように思われた。

WatchKit

プレリリースされたWatchKit SDKのページを見ると以下のように記載されている。

WatchKit apps have two parts: A WatchKit extension that runs on iPhone and a set of user interface resources that are installed on Apple Watch. When your app is launched on Apple Watch, the WatchKit extension on iPhone runs in the background to update the user interface and respond to user interactions.

すなわち、ウェアラブル端末であるApple Watchには、Storyboardやリソースファイルだけをインストールし、コンパニオンとなるスマートフォンであるiPhoneの側でApp Extensionとしてプログラムが動作する。Apple Watchのユーザーインターフェイスが操作されればそれはiPhoneのExtensionに伝わり、iPhoneのExtensionからApple Watchのユーザーインターフェイスを更新する。

これは最初の二つの予想のちょうど中間的なアーキテクチャと言える。アプリはiPhoneの側にその多くを置いて、ユーザーインターフェイスApple Watchの側で動作させる。結果として多くの問題が解決され、アプリはiPhoneの潤沢なリソースや機能を利用できるし、BLEで画面を送信する必要もない。

注意すべきは、Apple WatchとiPhoneの間のやりとりに遅延が生じることである。例えばユーザーインターフェイスが操作されたときのインタラクションはApple Watchの側で素早く表示しつつ、少し遅れてiPhoneでアクションが起きる、ということになる。このことで、iPhoneのExtensionからApple WatchのViewの様子を取得することができないようになっている。iPhoneの側で、Apple Watchのユーザーインターフェイスに行った操作を記憶しておく必要がある。

また画像リソースはなるべくApple Watchのリソースに含めておくべきである。それができない動的に生成または取得される画像は、キャッシュとしてApple Watchの側へ登録しておくことで、再表示するときのコストを大きく下げられる。

この他にも制限は多く、例えばカスタマイズされた独自のユーザーインターフェイス要素は、Apple Watchで利用できない。WatchKitで事前に用意されたユーザーインターフェイス要素だけを用いてデザインする必要がある。

総論

Apple WatchとWatchKitのSDKは、ウェアラブル端末に注意深く最適化されたものであることが読み取れる。WatchKitのアーキテクチャによって、優れたユーザーエクスペリエンスが得られるだろう。

またこれはApple Watchに限らず、その他のiOS関連機器にも有効なアーキテクチャであると考えられる。CarPlayApple TVのほか、将来登場するかもしれない新たな端末にも応用可能である。

いずれにせよWatchKitのこのアーキテクチャは、AppleiOSOS Xで長年開発してきた技術の結実である。

ところでWatchKitアプリに独自のユーザーインターフェイスを作ることは未来永劫できないのだろうか。恐らく答えはXcodeにある。Xcode 6から、Interface Builderに独自のViewを表示できるようになった。内部的には独自のViewをXcodeとは別のプロセスで動作させ、レンダリングさせているように見える。WatchKitアプリでも、Apple Watch側でカスタマイズしたViewだけを動作させることは技術的に可能になると予想できる。将来のWatchKitでそのような機能が搭載されるかもしれない。


※ 以上の内容はAppleによって公開された情報を元に書かれています。

モバイルアプリのObserverパターン

ReactiveCocoa勉強会関西にてObserverパターンについてお話ししましたので、以下にその内容をまとめます。


Observerパターンは、GoFの23のデザインパターンのうちの一つで、モデルが状態の変化をしビューに通知するパターンです。GUIアプリケーションの開発で多用されます。もちろんスマートフォンアプリの開発においても大変役に立つので、いくつかの例を挙げて見ていきます。

Objective-CのKey-Value Observing

static void * Context = &Context;


- (void)anything
{
    [object addObserver:self
             forKeyPath:NSStringFromSelector(@selector(property))
                options:NSKeyValueObservingOptionNew
                context:Context];
}


- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    if (context == Context) {
        doSomething();
    }
}

上記は監視する側の例です。NSKeyValueObservingプロトコルaddObserver:forKeyPath:options:contextを呼び出し、変化があったときobserveValueForKeyPath:ofObject:change:context:が呼ばれるというものです。NSStringFromSelector()contextを利用するのは良い習慣です。

self.property = object;
NSMutableArray *arrayProxy =
    [array mutableArrayValueForKeyPath:
        NSStringFromSelector(@selector(property))];
[proxy addObject:object];

KVOの通知を発火させるためには、Key-Value Codingに準拠するようにプロパティへの代入を行うか、あるいはコレクションのKVOを発火させるためにmutableArrayValueForKeyPath:が返すプロキシオブジェクトを利用します。

このようにObjective-Cでは、KVOという仕組みによってObserverパターンを簡単に利用できるようになっています。

AndroidJavaのObserverパターン

AndroidにおけるObserverパターンの実現ためには、素朴にObserverパターンを実装するほか、java.beansパッケージのPropertyChangeSupportクラスを利用する方法があります。

public class Bean {
    private final PropertyChangeSupport mChanges;

    private String mName;


    public Bean() {
        mChanges = new PropertyChangeSupport(this);
    }


    public void addListener(PropertyChangeListener listener) {
        mChanges.addPropertyChangeListener(listener);
    }


    public void deleteListener(PropertyChangeListener listener) {
        mChanges.removePropertyChangeListener(listener);
    }


    public String getName() { return mName; }


    public void setName(String name) {
        String oldName = mName;
        mName = name;
        mChanges.firePropertyChange("name", oldName, mName);
    }

}

PropertyChangeSupportインスタンスを保持し、PropertyChangeListenerインターフェースのオブジェクトを受け付けます。そして監視させたいフィールドの変更があったとき、firePropertyChange()を呼び出すことで、PropertyChangeListenerPropertyChangeEventが送られます。

java.beansパッケージの中で、このPropertyChangeSupport関連の機能だけがAndroidにも存在しています。KVOと似たような形で利用できるかもしれません。

またjava.util.Observableを継承するという方法もありますが、あまり使い勝手が良くないかもしれません。

Swift

Swiftについてはどうでしょうか。SwiftからもNSObjectのKVOは利用できます。しかし純粋なSwiftのオブジェクトについては、これまでのKVOは利用できません。

Appleのドキュメント“Using Swift with Cocoa and Objective-C”の“Adopting Cocoa Design Patterns”を参照すると、今日現在で

Information forthcoming.

となっています。正式なリリースまでに何か明らかになるとよいのですが。

ここからは与太話ですが、もしSwiftにKVOライクな仕組みが導入されるとしたら、Objective-Cのようなランタイムで動的に何かするのではなく、コンパイルタイムで解決できるような仕掛けになるのではないでしょうか。そのほうがSwift的で、より安全かつ最適化しやすいようにも思います。

以上となりますが、今後もライフワークとしてObserverパターンについて考えていきたいと思います。

iOSアプリ開発における便利OSSライブラリの選定について

f:id:cockscomb:20140506123733j:plain

(Andy Myers and the CocoaPods Dev team. Creative Commons - Attribution-NonCommercial 4.0 International)

iOSアプリを作るとき、今日ではCocoaPodsを用いて簡単に便利なライブラリの力を借りることができる。

ライブラリを利用するメリットは多い。自分でメンテナンスする必要がないので、放っておいても勝手に改善されていく。潜在的な問題があったとしても、多くの人が利用しているものなら誰かが気付いて直してくれる可能性も高い。また自分より優れたエンジニアの手によって、優れたインターフェースや実装になっているということも多い。何より、自分で実装する手間が省けるのがよい。

反面、デメリットについても考えなければならない。ライブラリがメンテナンスされなくなったとき、なにか問題が起こったり、あるいはAppleの気まぐれでコンパイルが通らなくなったらどうするのか。乗り換えるコストや、あるいは自分自身でメンテナンスすることを考慮する必要がある。またライブラリのインターフェースが全く変わってしまったら、これに対応するコストも必要である。リリースサイクルとの兼ね合いもある。

iOSアプリ開発においては、iOSが毎年大きなメジャーバージョンアップを繰り返すことや、言語仕様まで含めて開発環境が変わっていくことまで考慮しなければならない。もしアプリを一度リリースしてそれっきりで良いのなら何ら心配要らないだろう。しかし継続的なアップデートを数年にわたって続けていくつもりなら、無思慮なライブラリの選択はコードベースの寿命を縮める結果になりかねない。

ここで憚りながら、筆者のライブラリ選択の指針を公開する。参考になれば幸いである。

Effective Objective-C 2.0

Effective Objective-C 2.0

続きを読む

Web APIを利用するiOSアプリのテスト技法

もう先週ですが、表題のタイトルで「Consumer Service Engineer MeetUp Vol.1 ~iOS編~」という会でお話しさせていただきました。

このようなタイトルの発表にした理由についてですが、はてなとしてお話しするということで、ちょっと硬派な方に振ってみました。結果としては良いバランスだったのではないでしょうか。

発表資料を掲載します。

また以下に発表の概略を書いておきました。ご参考ください。

続きを読む

iOSアプリ開発関連書籍、大量入荷のお知らせと、おすすめの10冊まとめ

京都に本社を置きWebサービス事業を展開する会社で、WebサービスiOSアプリを作ったりしている。会社にはたくさんの技術書があるが、iOSアプリ開発関連の書籍がすこし足りないと感じていた。しかしながら読んでみたい本があったら自分で買ってしまうから、別に不自由すると言うこともなかった。というつもりだったのだけど、ちょっと気が変わって、会社にいい本が置いていないことは技術を重視するという社風から考えても好ましくない、という気になった。そこで上司に相談したところ、本はいくらでも買おう、ということだったので、買ってもらうことにした。

新しく買ってもらったものに加えて以前から会社にあったものも少し含むけれど、いま会社にあるいい本を以下に紹介します。

Objective-C

詳解 Objective-C 2.0 第3版

詳解 Objective-C 2.0 第3版

『詳解 Objective-C 2.0』は、Objective-C言語の言語仕様からFoundation.frameworkくらいまでをいわゆるObjective-Cと呼ぶとすると、そのほとんどすべてを正確にカバーしている。少し内容が古くなったとはいえ、そういうことは他の書籍で補うということにして、まず定番を抑えておくのがよい。

エキスパートObjective-Cプログラミング ?iOS/OS Xのメモリ管理とマルチスレッド?

エキスパートObjective-Cプログラミング ?iOS/OS Xのメモリ管理とマルチスレッド?

ARC・Blocks・GCDの3つのトピックについて専門的に書かれている。ARCの細かな挙動に気を配ることはメモリ関連の問題を減らすために必要となるし、BlocksやGCDの細かな部分は少し複雑かもしれないが便利な仕組みが多い。『エキスパートObjective-Cプログラミング』で詳しく学んでおいて損になることはない。

Effective Objective-C 2.0

Effective Objective-C 2.0

少し前までだったらここまでの2冊が特によかったと思うが、いまだったらこの1冊も推したい。コードを書く上で、言語毎に好ましい習慣があるように思う。そういったことを自力で習得するのは容易ではない。『Effective Objective-C 2.0』にはそういうことが丁寧に書かれている。

iOSのメジャーリリース毎に出ている書籍

iPhoneアプリ開発エキスパートガイド iOS 6対応

iPhoneアプリ開発エキスパートガイド iOS 6対応

上を目指すプログラマーのためのiPhoneアプリ開発テクニック iOS 7編

上を目指すプログラマーのためのiPhoneアプリ開発テクニック iOS 7編

iOSはメジャーバージョンが上がる毎にその開発環境も大きく変わっていく。昨今であれば、StoryboardやAuto Layoutなどは、大きく開発の仕組みを変えたといってよいだろう。そのときそのときで十分キャッチアップしていくのがいちばんよいし、これにはApple自身のドキュメントやサンプルコードが役立つ。とはいえ、細かい部分は見逃しがちであるし、ちょっと離れているとまるで分からなくなってしまう。そういったときにこのような書籍が役立つと思う。

単なるフレームワークの解説にとどまらず、便利なテクニックまで紹介されているのがよい。会社には新たにiOS 6とiOS 7の2冊を買ってもらったが、古いバージョン向けの『iOS4プログラミングブック』と『iOS5プログラミングブック』も役立つと思う。

もう少し特定の分野に絞った書籍

iOS Core Data徹底入門

iOS Core Data徹底入門

Core DataはiOS/OS Xで使われる標準的なデータベースの仕組みである。かなり高レベルに抽象化され、一種独特とも言える。その分iCloudとの連携など非常に高度な機能が備わっており、必要な場合に利用できることは大きな助けになる。そういうCore Dataについて、かなり網羅的に書かれているのが『iOS Core Data徹底入門』である。

最初の2/3ほどはあまりCore Dataと関係なく、データの永続化についてのいくつかのやり方やSQLiteを使う方法などが書かれており、残りでCore Dataを説明する。Core Dataについては簡単な利用法からマイグレーション、さらに例えば大きなバイナリデータをどうしても格納したいときにパフォーマンスをなるべく劣化させないテクニックといったところまで、かなり広く書かれている。

反対に、書かれていないこともある。例えばマルチスレッドからCore Dataを扱うということがよくあるが、NSManagedObjectContextが持っているキューを利用するやり方や、あるいはNSManagedObjectContextの親子関係を用いる方法といった、比較的新しい (といってもiOS 5から使える) 部分について特に記載がない。昔ながらのやり方だと煩雑なので、この辺りの記述がほしかった。またNSIncrementalStoreというおもしろいやつがあって、あまり使われることはないけれど、書いてあるとおもしろかったと思う。

とはいえ、日本語でCore Dataについてこれほどの情報源はなかなかないから、持っておくとよいと思う。マルチスレッドのときの新しいやり方はWWDC 2012のセッションがよかった。

iPhone/iPad グラフィックスプログラミング』はiOS/OS Xのグラフィックス関連のAPI群を紹介している。グラフィクス関連のフレームワークは非常に多く、Core GraphicsやCore ImageにCore Animation、ImageIOなど多岐にわたる。例えばアニメーションGIFを作るやり方みたいなところまで詳細に書かれており、便利なことも多いと思う。

開発手法

iOSデバッグ&最適化技法―for iPad/iPhone

iOSデバッグ&最適化技法―for iPad/iPhone

バグに繋がりやすい部分をよく理解し、効率的なデバッグのやり方を知っていると、開発の効率もよくなる。パフォーマンス上の問題にぶつかったとき、何より計測することが解決の近道である。そういうことを専門的に取り扱ったのが『iOSデバッグ&最適化技法』で、いくつかのトピックについて必要な情報が書かれている。ちょっと経験のある人だったら大体わかっているようなことが大体書いてあるので、とても役立つと思う。

UI

スマートフォンアプリのUIには一定の規則性がある。そういった規則を意識することで統一された使用感が得られる。『スマートフォンのためのUIデザイン』ではそういった規則を、実際のたくさんの事例を元に紹介している。どういったときにどういったUIコンポーネントが使われるのか、どういった意味合いがあるのか、といったことを学ぶことでいきなり異常なUIを作ることがなくなってよい。

iOS 7になってUIが全面的に見直された。いわゆるフラットデザインであるが、コンテンツを重視してUIパーツを従属的なものとし、リアリティのある奥行きの表現や物理法則の採用によって現実の延長線上にUIを位置づけた、といった風な大きな変更である。『iOS 7デザインスタンダード』はそういった変化を丁寧に説明している。好ましいことに、UIコンポーネントの名前が正確に記述されていて、コミュニケーションにも役立つと思う。

結びの言葉

上に紹介した書籍の多くは、自分で既に買っていてよかったものである。iOSアプリ開発関連の書籍をすべて読んでいるわけではないから、もっとよい本があるのを知らないということも多いだろうと思う。そういうのがありましたら是非、ご教示いただけたら幸いです。

今回紹介した10冊のうち2冊は以前から会社に置いてあったもので、8冊は新規に購入していただけた。これらの書籍からよく学び、またこの知識を拡大し、社内におけるさらなる技術向上に努めたい。そしてその結果を必ず製品に反映させたい。

iOS/OS Xアプリ開発関連の書籍について、昔からのよい本もあるけれど、やはり年々充実してきている。Objective-Cについて丁寧に書かれた本もどんどん増えていて、チェックが追いつかないほどになっている。そういった中で、すべての領域が網羅されたかと言えば決してそういうわけではない。書籍から学べる領域というのはいまもむかしも限定的で、必要に応じて自ら学び取っていかなければならない。

とはいえ、書籍でカバーされたら良いだろうと思う領域はある。例えばテストについて、テストは誰にでも関係あるのだから、そろそろ書籍としてまとめられても良いのではないか。『iOSテストについて書かれているおすすめ電子書籍情報(洋書) - laiso+iphone』ここで書かれているように、洋書ではいくつか書かれたものがある。少し特化すると、例えばiOSにおけるオーディオ処理について以前は『iPhone Core Audioプログラミング』というのがあったが、絶版となってしまった。

今後ますますよい本が発刊されていくことに疑いの余地はないし、とても楽しみである。

iOS 7におけるUIStatusBarStyleのベストプラクティス

photo by Janitors

前提

iOS 7からView Controller単位でステータスバーを設定しやすいようになりました。

ベストプラクティス

Info.plist

はじめに、Info.plistでUIViewControllerBasedStatusBarAppearanceNOになっていないことを確認します。NOだったらこれまでと同様

[UIApplication sharedApplication].statusBarStyle

で設定することになります。

アプリ起動時のDefaultイメージでは、Info.plistが優先されるので、Info.plistでUIStatusBarStyleを設定しておきます。

UIViewController

ここからView Controllerでの設定についてみていきます。重要なのはUIViewControllerのふたつのメソッドです。

preferredStatusBarStyle

ひとつめは

- (UIStatusBarStyle)preferredStatusBarStyle

で、これはそのView Controllerがどういうステータスバーが良いかを表現するためのメソッドです。適宜オーバーライドして、UIStatusBarStyleDefaultUIStatusBarStyleLightContentのどちらかを返します。

childViewControllerForStatusBarStyle

もうひとつは

- (UIViewController *)childViewControllerForStatusBarStyle

です。このメソッドでnilを返すと、上で説明したpreferredStatusBarStyleが使われます。なんらかのView Controllerを返したときは返したView Controllerの要求に従います。このメソッドはView Controllerのコンテナ的なView Controllerで使われます。例えばUITabBarControllerではこのメソッドが実装されていて、selectedViewControllerが返っているように見えます。

コンテナ

ここからが問題で、UINavigationControllerではchildViewControllerForStatusBarStylenilを返しています。とはいえNavigation Controllerを使っていてステータスバーのスタイルを変えたいとき、UINavigationControllerをサブクラスするのは感心しません。よりよいのは、UINavigationBar

@property(nonatomic, assign) UIBarStyle barStyle

を設定することです。UIBarStyleにはUIBarStyleDefaultUIBarStyleBlackがあります。これらが設定されたとき、UIStatusBarStyleはそれぞれUIStatusBarStyleDefaultUIStatusBarStyleLightContentになります。

追記(2016/07/01)

navigationBarHidden が真のとき、visibleViewControllerchildViewControllerForStatusBarStyle になるそうです。Navigation Bar の色合いなどを反映する必要がないので、納得ですね。

あとUISplitViewControllerのときはどうしたらいいのか分からなかった。サブクラスしてpreferredStatusBarStyleをオーバーライドする以外になんかできるなら知りたいので皆さまの知見を募集いたします。

参考

iOS Keys

Mastering iOS 7 UIStatusBarStyle (Example) | Coderwall

Livre

アプリの説明にこんな方にオススメっていう欄があって

はてなブログ、Ameba(アメーバ)ブログ、livedoorブログが続かなかった方

ということだった。

f:id:cockscomb:20131011232305j:plain

なんとかがんばって続けてほしいと思います。