2015年7月31日金曜日

iOS 9 の split screen に対応するサンプルプロジェクトを作成してみました

WWDCでの発表でもありましたとおり、iOS 9からはiPadで画面を二分割して複数のアプリケーションを同時に実行することができるようになります。このSplit Screen機能に対応するためには、iOS 8で導入されたAdaptive User Interfaceを活用する必要があります。

参考:



Adaptive User Interfaceな実装をする上で最も簡単な対応方法はひとつのUIViewControllerで複数のSize Classeに対応することです。大体のケース、例えばApple標準のMapアプリやメールアプリなどはこれで問題がないのですが、例えば横方向がRegularサイズの場合(=iPadやiPhone 6 plusなど横に広いデバイスの場合)はUICollectionViewを使ってタイル上に広くアイテムを並べ、横がCompactなデバイス(縦向きのiPhoneなど)の場合はUITableViewを使って縦に多数のアイテムを並べたいという需要があったりします。この場合、ひとつのUIViewControllerでどちらにも対応するのがかなり困難になり、シンプルな実装になりません。

そこでSize Classに応じてdynamicに複数のUIViewControllerを差し替えて表示するサンプルを作ってみました。



特徴:

  • Size Class変更時にきちんとアニメーションします
  • 当然Split Screenにも対応しています


iOS 9は既存のコードをAdaptive User Interfaceに対応させる良い機会だと思いますので、これを機会に皆さんも自分のアプリを見なおしてみてはいかがでしょうか?

2015年4月10日金曜日

Apple Watch の実機を触ってわかった、アプリ開発者が抑えておくべきポイント


本日からついにApple Watchの実機がお目見えとなりました。私も早速Apple Storeに行って試着・試用してきたのですが、予想以上にアプリ開発に影響がありそうな点が多数見つかりましたので、思うところをブログ記事にまとめて公開しようかと思います。

■小さい、とにかく小さい

Apple Watchの実機を身につけてまず最初に感じるのがその圧倒的な小ささです。この小ささというのは

  • これまでのAndroid Wearデバイスのどれと比べても感じる相対的な小ささ
  • Apple Watch上で表示されているUIを見て感じる絶対的な小ささ

の2つの要素から感じられます。

試しに私が身につけているAndroid WearデバイスとApple Watch Standard 42mmを並べて写真をとってみたのですが、見ての通り42mmモデルですら表示領域がずいぶんと小さいのがわかります。

その上Apple WatchのUIは全体的にAndroid WearのUIと比べて密度が高い用に感じられます。こちらのブログに具体的な例があるのでぜひ参照していただきたいのですが、見ての通り同じアプリでもApple Watchのほうが詰まったUIになっています。ただでさえデバイス自体が小さめな上に密度の高いUI、具体的にはアプリ内で常時上にナビゲーション領域が表示されたりする、ということでなおさら小ささが際立っているわけです。

小ささをより体感するために、iPhone 6の画面でApple Watch 38mmの画面サイズを表現してみました。

アイコンが一つにラベルが一つプラスアルファ程度がせいぜいの大きさしか無い、というのがよく分かるかと思います。

したがって繰り返し繰り返し随所で述べられていると思いますが、画面上に表示する要素は徹底的に少なくする必要があります。私も十分に少ない要素だけを画面に表示するように心がけていたつもりでしたが、実際にデバイスに触れたあとに見返すとまだまだ要素が多すぎるぐらいです。少なすぎるのではと心配になるぐらいまで減らしてちょうどいいのではないでしょうか。

Appleの標準のアプリなどでかなり高密度なUIを採用しているものもありますが、そこは真似しないほうが良いと考えています。具体的には標準のマップアプリなどは38mmモデルの上では細かすぎて地図を読み取るのが極めて困難でした。

■Glanceこそがすべて

Apple Watchのインターフェースのナビゲーションは以下の図のようになっています。

基本は時計フェイスが表示されていて、そこから竜頭を押すとHomeに遷移してアプリを選択して起動することができます。時計フェイスを下にスワイプすると上からNotification Centerが表示され、上にスワイプすると下からGlanceが表示されます。Glanceは左右スワイプで次々に閲覧することができます。感覚的にはGlanceはiOSデバイスにおけるWidgetのようなもので、常時Widgetが時計フェイスの下に並んでいるようなイメージをするとわかりやすかったです。

このインターフェースの中でアプリができることで、最も重要になってくるのがGlanceです。操作してみてわかったのですが、Home画面からアプリを起動するのはただでさえ小さいWatchの画面上に無数の小さいアイコンが並ぶため困難苦痛を極めます。したがって必然的にアプリの状態を確認したりアプリを起動するのはGlanceを使うのが最も楽でスピーディで良いということになります。GlanceこそがApple Watchアプリにおけるすべての窓口と言えそうです。ここをどれだけ便利に使いやすく見せるかによってアプリの価値が変わってくるかもしれません。

■ネイティブアプリは速いが転送は遅い?

気になるApple Watchの動作速度ですが、まず通常の用途ですとかなりサクサクと動作しました。時計フェイスから通知センターに遷移したりGlanceを見たり、Glance間を切り替えたりするぶんには素晴らしい応答速度で、手元のAndroid Wearデバイスよりも機敏に感じました。

これがアプリとなってくるとだんだんと遅さが感じられる場面が出てきます。気になった点としては、

  • いくつかのGlanceについてロードが終わらない、ないしロードが遅すぎる。マップ・天気・株価が該当。
  • GlanceまたはHomeからのアプリの起動が遅いときがある。フィットネスで該当。
  • フィットネスで「開始」ボタンを選択してから実際に開始するまでに明らかに感じられる遅れがあった。
  • マップアプリについてはロードが遅く、地図が表示されるのも遅い。

これらから推測するに、おそらくネイティブでアプリが動作している部分に関しては素晴らしいパフォーマンスが得られているものの、本体側のiPhoneからデータを転送している箇所に関しては顕著にパフォーマンスが落ちているのではないか思われます。

今回体験する事ができた実機にはサードパーティ製のアプリが入っていなかったので、我々開発者が作ったアプリに関してどの程度のパフォーマンスが得られるのかは全く不明ですが、この調子ではあまり良い結果が得られないかもしれません。今後のSDKの拡張でApple Watchネイティブのアプリが作れるようになるまでは、本体からデータを転送する頻度および転送量を少しでも削減できるようなつくりを目指すしかなさそうです。

■妄想とか将来の話

その他現状はサードパーティ開発者からは使えないのですが、将来的に面白くなりそうだと思った点を挙げます。

まず竜頭コントロールについてですが、現状竜頭コントロール入力をアプリ側から取得することができないのはみなさんご存知のとおりです。触った感じ竜頭自体は非常に良く出来ていたのですが、画面のどの箇所が竜頭でコントロールできるのか出来ないのかがいまいちよくわからないという問題があるように思えます。最も顕著な例は時計フェイスのカスタマイズUIで、これはカスタマイズする箇所をタップしてから竜頭で項目を選択するという仕組みになっているのですが、直感的に非常にわかりづらかったです。きちんと考えて統一的に使われていれば便利かもしれませんが、画面のタッチとの併用がほぼ必須なため竜頭だけでコントロールできなかったりなど、課題が山積みのように感じます。

逆にForce Touch(強く力を込めて押しこむようにタップする)機能ですが、これは非常に優れているように感じました。ダブルタップと特性は似ていますが、精密動作を必要とせずTapticエンジンによるフィードバックによって入力成功が伝わる点を考えてもダブルタップより圧倒的に優れている入力方式と言えます。現状Force Touchは自由に使うことができずメニューの表示用途に限定されていますが、これはまずForce Touchという操作の存在を確実にユーザーに理解してもらうという意味で良いと思います。この操作が広まればゆくゆくはiPhoneやiPadにもForce Touch搭載されることが確実でしょうし、アプリは積極的にForce Touchを取り入れていくべきと思いました。

将来的にForce TouchがiPhoneに導入されるとなると、iOSのAndroidに対する現在の弱点であるメニューボタンの不在を補う重要な役割になってくるかもしれませんね。さらにゲームでも大変有効に使える入力方式に間違いありません!夢が広がります。

Force Touchといえばその対となるTapticエンジンも非常に素晴らしかったです。Force Touch時のフィードバック、通知時のフィードバック、友人へのハートビートの送信、すべてで全く異なる触覚が伝わってくるのがまさに見事でした。まったく画面を見なくても触覚の違いだけで何が起こっているのかを判別できるほどです。現状Tapticエンジンを自由に触ることはできませんが、もし開放されたらTapticからのフィードバックだけで画面を全く見ないでも十分に使えるアプリが作れるかもしれません。全くユーザーを煩わせることない究極のUIになりうるかもしれませんね。

最後にGlanceについてちょっと触れます。基本的に現在サードパーティのアプリがGlanceでできるのは情報を表示するだけで、Glanceがタップされた時の挙動もWatchアプリが起動するだけに固定されてしまっています。

ところがAppleのネイティブアプリである心拍数Glanceについては、なんとGlanceが表示された瞬間に心拍数が自動的に計測開始され、さらにボタンをタップするとダイアログが表示されるというつくりになっていました。すなわち機能が開放されていないだけでリッチなGlanceを作ることも可能なようです。先にGlanceこそがすべてだと述べましたが、このリッチなGlanceを作る機能が開放されたらApple Watchのサードパーティアプリの可能性は更に広がると思います。

2015年3月16日月曜日

WatchKit 向けの UIImage Animation を簡単に実装するためのライブラリ ParaMangar を作りました

いよいよApple Watch発売日まで1ヶ月ということで皆様精力的にWatch向けのアプリを作成されているのではないかと思いますが、現状のWatchKitで誰もが一度はマジギレ不満に思う点がアニメーションです。

こちらのブログにある通り、WatchKit向けのアニメーションを作成するのは現状極めて面倒と言わざるを得ません。

http://d.hatena.ne.jp/shu223/20150214/1423901142

そこでiOS側でUIViewを今までどおりレンダリングして、その結果をファイルにしたりUIImageにしてWatchKitに渡せばいいじゃない!というライブラリを書いてみたので公開いたします。

https://github.com/akisute/ParaMangar

このParaMangarを使うとこんな感じでアニメーションが作れます。


ライセンスはMITです。
あまりテスト出来ていないのでバグだらけかもしれませんが、ご意見issueなどgithubでお寄せいただければ幸いでございます!!

2015年2月2日月曜日

YouTube などのフルスクリーンで再生される UIWebView の動画をプログラムから終了させる方法

UIWebViewでyoutube.comやvine.coなどのサイトの動画を開いた場合、動画がフルスクリーンの専用動画プレイヤーViewControllerで再生されることがあります。このフルスクリーン動画を閉じる方法です。

方法1: 安全な方法

JavaScriptのFullscreen APIを使って安全に閉じることができます。iOS 6以上で動作確認済みです。

Fullscreen APIについては以下の資料が詳しいです。


方法2: animated, completionの制御もしたい場合

ここからがお待ちかねの黒魔法になります。
先ほどのJavaScriptを使った方法ではフルスクリーン動画を閉じる際のアニメーションを制御できません(必ずアニメーションが発生します)。またフルスクリーン動画を閉じ終わったタイミングのcompletion handlerが存在しません(JavaScriptでハンドルしようにも、videoタグのonendedイベントは通常の再生終了時にもイベントが飛ぶ上にアニメーション終了時ではなく再生終了時にイベントが飛ぶため使いづらい)。

通常はこれらが問題になることはまずありませんし、万一あったとしても仕様のほうを変えるほうが適切ですが、何らかの止むに止まれぬ理由によりなんとかしなければならなくなる場合が稀によくあります。

そこで画面上にUIWebView経由で表示されている動画プレイヤーViewControllerをビュー階層をたどって見つけ出し無理矢理dismissViewController:completion:で消すという方法を取ります。iOS 6以上にて動作確認済みです。ただしiOS 7以下の場合とiOS 8の場合で全く構造が異なり、将来にわたって動作するか非常に怪しいです。

Private APIの名前がバリバリ含まれるコードになっておりますので審査に出すアプリには使用しないことを強くおすすめさせていただきます。

2015年1月15日木曜日

ReactiveCocoa を Swift から使ってみた(2) KVO編

前回の記事から引き続き、ReactiveCocoaを触ったりしています。FRPの概念に慣れてくると通常のプログラミングスタイルでは得られない知見に遭遇出来てなかなか面白いです。

今回はまずSwiftでReactiveCocoaを学ぶときに参考にするドキュメントについてご紹介したいと思います。といってもSwiftに特化したドキュメントはほとんど存在しないため、Objective-CでReactiveCocoaを学ぶときのドキュメントを見て学ぶしか無いのが現状です。

私は個人的にはサンプルコードを直接触るほうが性に合っているようなので、以下のオープンソースのReactiveCocoaで作られたアプリのコードを見ています。
https://github.com/AshFurrow/C-41
https://github.com/jspahrsummers/GroceryList
GroceryListのほうがより本格的にFRPっぽい書き方をしているのでオススメです。実際にコードを動かしたい場合はC-41のほうが比較的簡単に動かしやすいと思います(それでも使われているライブラリが古いためビルドを通すのが大変だったりしますが・・・)

SwiftでReactiveCocoaを使っている例としてはCarthageが良いと思います。ただしMacのコマンドラインアプリなのでUIまわりがらみのサンプルとしては余り参考になりませんでした。
https://github.com/Carthage/Carthage

例えばReactiveCocoaを使う上でどうしても欠かせないのがRACObserveを使った特定プロパティに対するKVOのシグナル化です。これにより特定のプロパティが変化した時にシグナルを受け取ることができるようになります。通常Objective-CでReactiveCocoaを使う場合は標準のRACObserveというマクロを使用すれば良いのですが、Swiftではマクロが使用できないため他の方法を採用する必要があります。

調べてみたところ、幸いにしてRACObserveマクロは単なるNSObjectのrac_valuesForKeyPathメソッドのラッパですので、以下のようにしてrac_valuesForKeyPathを使用すれば解決できます。


ここで注意することとして、KVO対象となるプロパティにはdynamic修飾子を付ける必要があります。Objective-Cにもdynamic修飾子はありましたが、Swiftのdynamic修飾子はObjective-Cのものとは意味が異なりdynamic修飾子を付けたプロパティについてObjective-Cと同様に動的プロパティアクセスを行うようにする(具体的にはobjc_msgSendする?)という意味があります。詳細については以下の記事を参照してみてください。
http://stackoverflow.com/questions/24092285/is-key-value-observation-kvo-available-in-swift#comment39273366_24092370
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html

2015年1月1日木曜日

Swiftプログラマ格付けチェック (2015新年スペシャル)

Swiftプログラマ格付けチェック

今回一流のSwiftプログラマの皆さんに格付けチェックしていただくのはこちら!

JSONライブラリ

です!

ひとつは日本が誇る一流プログラマ、dankogai氏が作成されたJSONライブラリ、githubスター数312
ひとつは当ブログ管理人三流プログラマ、akisuteが適当にググって見つけたJSONライブラリ、スター数16
となっております。
皆様にはこの2つのうちからdankogai氏のライブラリを当てていただきます!

Aのライブラリ
Bのライブラリ
(コメントはすべて削除しています)

それでは正解だと思ったほうの部屋に入っていただきましょう!

Aが正解だと思った人の部屋
Bが正解だと思った人の部屋