cockscomblog?

cockscomb on hatena blog

NSWindowのタイトルバーをカスタマイズする

人類の多年の夢であったNSWindowのタイトルバーのカスタマイズであるが、YosemiteになってついにオフィシャルなAPIが実装された。


YosemiteではApple製のアプリケーションほとんどにおいてデザインが一新され、かつてOS Xを特徴付けていたツルッとしたテクスチャは取り払われた。そしてウインドウのタイトルバーまでもが変わった。

f:id:cockscomb:20150208004605p:plain
タイトルバー

ウインドウのタイトルバーは、OS XにおいてGUIアプリケーションの要である。タイトルバー自体がウインドウを移動するためのノブであり、左にはウインドウを操作するための赤・黄・青のコントロールが、中央にはウインドウのタイトルが表示される。ときにはツールバーと見かけ上くっついたりするが、いずれにしてもウインドウの中心はタイトルバーである。

f:id:cockscomb:20150208005228p:plain
Safariのタイトルバーにはツールバーが表示されている

そのタイトルバーをカスタマイズしたい、これは全人類が生まれながらに持っている当然の欲求である。そして、しかし、Appleは長年にわたってそういったAPIを提供してこなかった。ウインドウをウインドウたらしめるタイトルバーを、心ないデベロッパーが欲望のままに毀損することを許さないというように、禁断の果実を決して手放そうとはしなかった。それがYosemiteになって、Apple製のアプリケーションでさえ、一般的なタイトルバーのルールを破壊した。いまやタイトルバーには信号機のようなコントロールを残して、タイトルの代わりにツールバーが表示されたり、あるいはウインドウのコンテンツがそのまま表示されるようになった。これはいまやAppleだけの特権ではなく、ついにAPIが提供されたのである。

f:id:cockscomb:20150208005317p:plain
リマインダーのタイトルバーはコンテンツと重なる

タイトルを非表示にする

OS X 10.10 YosemiteからNSWindowに新しく追加されたプロパティvar titleVisibility: NSWindowTitleVisibilityを使うと、ウインドウのタイトルを非表示にできる。enum NSWindowTitleVisibilityは以下のように二つの値からなる。

enum NSWindowTitleVisibility : Int {
    case Visible
    case Hidden
}

デフォルトは.Visibleであるが、ここでヘッダから.Hiddenのコメントを引用する。

The always hidden mode hides the title and moves the toolbar up into the area previously occupied by the title.

NSToolbarがある場合にはタイトルがあった場所に移動するようだ。これによって、例えばSafariやカレンダーのように、タイトルバーの高さが少し高く、信号機のようなコントロールのすぐ右にツールバーがあるようなウインドウが作れる。NSWindowNSToolbarを設定して、あとは以下のようなコードをNSWindowControllerfunc windowDidLoad()などに実装する。

window?.titleVisibility = .Hidden

f:id:cockscomb:20150208005920p:plain
単にツールバーを置いたウインドウ

f:id:cockscomb:20150208005928p:plain
ツールバーを置いてtitleVisibility = .Hiddenとしたウインドウ

タイトルバーを装飾する

OS X 10.10 YosemiteではNSViewControllerが大幅に強化され、iOSUIViewControllerから多くの思想を受け継いだ。そして同時にNSViewControllerのサブクラスがいくつか追加された。その一つがNSTitlebarAccessoryViewControllerである。

NSTitlebarAccessoryViewControllerは、その名前が示す通り、タイトルバーを装飾するViewのControllerである。このViewControllerのviewプロパティが返すViewが、NSWindowのタイトルバーに表示される。合わせてNSWindowにも以下のようなプロパティやメソッドが追加されている。

var titlebarAccessoryViewControllers: [AnyObject]
func addTitlebarAccessoryViewController(childViewController: NSTitlebarAccessoryViewController)
func insertTitlebarAccessoryViewController(childViewController: NSTitlebarAccessoryViewController, atIndex index: Int)
func removeTitlebarAccessoryViewControllerAtIndex(index: Int)

NSWindow複数NSTitlebarAccessoryViewControllerを順序付きで管理する。タイトルバーの中でどの部分に表示されるのかは、NSTitlebarAccessoryViewControllerの持つvar layoutAttribute: NSLayoutAttributeというプロパティで決定される。ただし現在の所NSLayoutAttributeのうち有効な値は.Bottom.Rightのみであることがヘッダに書かれている。もちろんそれぞれに対応する位置は、タイトルバーの下と右である。

実際に表示するには以下のようなコードを、例えばNSWindowControllerfunc windowDidLoad()に実装する。NSTitlebarAccessoryViewControllerインスタンスはStoryboardから生成している。

let accessory = storyboard?.instantiateControllerWithIdentifier("TitlebarAccessory") as NSTitlebarAccessoryViewController
accessory.layoutAttribute = .Right
window?.addTitlebarAccessoryViewController(accessory)

f:id:cockscomb:20150208010129p:plain
layoutAttribute = .BottomNSTitlebarAccessoryViewControllerを設定したウインドウ

f:id:cockscomb:20150208010116p:plain
layoutAttribute = .RightNSTitlebarAccessoryViewControllerを設定したウインドウ

コンテンツをタイトルバーの領域まで拡げる

タイトルバーの位置までウインドウのコンテンツを表示するために、新たにvar titlebarAppearsTransparent: Boolプロパティと、NSFullSizeContentViewWindowMask定数が用意された。

titlebarAppearsTransparentはタイトルバーの背景を透明にするかどうかを表す。NSFullSizeContentViewWindowMaskは、NSWindowvar styleMask: Intプロパティに利用する定数で、タイトルバーの領域までをコンテンツの領域とすることを表現するものである。

NSFullSizeContentViewWindowMaskNSScrollViewの組み合わせによって、タイトルバーの下にコンテンツが透けるような表現が可能になる。またNSFullSizeContentViewWindowMaskを設定した上でtitlebarAppearsTransparentを真にすると、信号のようなコントロールだけのウインドウが作れるのだ。

window?.titleVisibility = .Hidden
window?.styleMask |= NSFullSizeContentViewWindowMask
window?.titlebarAppearsTransparent = true

f:id:cockscomb:20150208010259p:plain
タイトルバーの部分までNSSplitViewのコンテンツを表示させるようにしたウインドウ

伝統的手法

有史以来、NSWindowのタイトルバーをカスタマイズすると言えば大きく二つの方法があり、ひとつはウインドウのコントロールまで完全に自作して自由に表示する方法、そしてもうひとつはwindow.contentView.superviewという風にNSWindowの実装に依存してビューの階層を辿る方法である。現実的には主に後者が利用されることが多かったのではないだろうか。(NSThemeFrameなどで検索するとそういった方法を指し示すページが今も見つかるだろう。)

しかしOS X 10.10 Yosemiteでは、このビューの階層を辿る方法を使っていると"NSWindow warning: adding an unknown subview:"というログが出力されるようになり、代わりにオフィシャルな方法が提供されることになった。このことはAppKitのリリースノートに記載されている。

まとめ

ここまでで、OS X 10.10 Yosemiteから追加されたAPIによって、柔軟にタイトルバーをカスタマイズできることがわかった。これらはもちろん組み合わせることもできる。例えばSafariでは、titlebarAppearsTransparent = trueとした上でlayoutAttribute = .BottomNSTitlebarAccessoryViewControllerを設定しているかもしれない。

f:id:cockscomb:20150208010722p:plain
SafariのようにtitlebarAppearsTransparent = trueかつlayoutAttribute = .BottomNSTitlebarAccessoryViewControllerを設定したウインドウ

また昨今噂されるUXKitでは、UXNavigationControllerなどUIKit由来の機能が存在するらしい。これらのNSWindowの新しいAPIを使って、例えばUINavigationBar相当の機能をタイトルバーに押し込めることもできるのではないだろうか。

まだ見ぬOS X 10.11への期待を膨らませつつ、読者諸氏もNSWindowのタイトルバーをカスタマイズしてみてほしい。こちらからは以上だ。


詳解 Swift

詳解 Swift

砦を破壊する技術

みんな楽しそうに遊んでいてけまらしいので、Besiege買った。僕だって物理エンジンの世界で城砦を破壊してみたい。

古来より城攻めには投石器と相場は決まっており、かの芭蕉も「夏草や 兵どもが 夢のあと」という句で投石器の威力を詠っている。

f:id:cockscomb:20150205222218p:plain
見よ、これが投石機の雄姿である

どうせ一度きりの人生、ただの石ではなく爆弾を発射したいものである。

f:id:cockscomb:20150205222223p:plain
投石に失敗すると自爆する……

物理エンジンだけあって、現実世界と同じように失敗したりもする。人生に筋書きは存在しない。

f:id:cockscomb:20150205222227p:plain
美しい投石フォーム

画像だけでは伝わりづらいかもしれませんので動画を撮りました。

おもしろいので皆さんもどうぞ。

Androidアプリ開発を始めるときに読む本

今年はついにAndroidアプリを作りました。Androidアプリを開発するに当たって、Java言語にもAndroidプラットフォームにも明るくなかったので、勉強しようと本を読みました。いろいろ読みましたが、そのうち特によかったものを紹介します。

Java言語

Effective Java

Javaをちゃんと書けるようにしようと思って読みました。JavaのSerializableやClonableの挙動について知識を得られたし、Javaの言語上の特性を意識した設計について一定の視座を得られたように思います。読まずにJavaを書けていたとは思えないので、大変有意義でした。『並行性』の章などはまた再読したいと思います。

EFFECTIVE JAVA 第2版 (The Java Series)

EFFECTIVE JAVA 第2版 (The Java Series)

Android

プロの力が身につくAndroidプログラミングの教科書

ActivityやServiceにContentProvider、レイアウト、テストなど、一通り書いてあります。おおよそ網羅的で、どのような要素があるのかを最初に把握できます。これはアプリの設計においてなるべく正しい手段を選択するために必要なことだと思います。とにかく一通り書いてあるというのがとても良くて、なかなか他にはありませんでした。Androidアプリの開発を学ぶときに最初に手に取るべきは本書だと思います。

プロの力が身につく Androidプログラミングの教科書

プロの力が身につく Androidプログラミングの教科書

Master of Fragment

Fragmentのライフサイクルや復元、Support LibraryのFragmentについて、あるいはアニメーションについてなど、Fragmentについて学ぶべきほとんどのことが書いてあります。AndroidではFragmentでけっこうハマると思うので、Fragmentを活用したいならこれを読むとよいでしょう。

達人出版会でベータ版が買えるという状態ですが、いろいろなフォーマットに対応しているので不便はないと思います。

Master of Fragment (Android Professional Developerシリーズ)
あんざいゆき, わかめまさひろ
達人出版会
発行日: 2014-02-14
対応フォーマット: PDF, EPUB

Android Security 安全なアプリケーションを作成するために

AndroidiOSより自由度が高く、アプリ間の連携の仕組みもリッチですが、その副作用としてセキュアじゃないアプリを簡単に作れてしまいます。本書はAndroidの基本的なセキュリティの仕組みから解説されていて、とても役立ちます。Androidアプリを作るときには必ず理解しておきたい内容が書かれています。

Android Security  安全なアプリケーションを作成するために

Android Security  安全なアプリケーションを作成するために

Androidアプリ開発のセキュリティについては『Androidアプリのセキュア設計・セキュアコーディングガイド』も役に立ちます。

まとめ

Androidアプリ開発に入門するには、大体上記の4冊くらいを読めばよいと思います。あとはGoogleのドキュメントを眺めるとか、APIのdiffを全部見るとか、最新のイケてるライブラリを調べるとかするのがよいでしょう。技術の進歩が早い分野ですから、絶えず知識をアップデートしていく必要があります。

これから年末年始で、退屈凌ぎにAndroidアプリ開発を学ぼうという皆さんのお役に立てたらと思います。

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によって公開された情報を元に書かれています。

「記憶に残る風景」 #地元発見伝

「記憶に残る風景」 #地元発見伝

https://www.google.com/maps/preview?q=43.086833%2C141.317335

札幌市, 北海道

小学校。

https://www.google.com/maps/preview?q=43.080485%2C141.315322

札幌市, 北海道

中学校。

https://www.google.com/maps/preview?q=43.090155%2C141.333653

札幌市, 北海道

高校。

https://www.google.com/maps/preview?q=43.07828%2C141.341148

Google Maps

大学。

地元の魅力を発見しよう!特別企画「地元発見伝

http://partner.hatena.ne.jp/jimoto/


その辺にたくさんうろついている人間たちには、それぞれの人生があって、それぞれの地元がある。僕は就職して京都のインターネットサービスの会社で働いているけど、地元は札幌。

地元にはいろいろあるけど、最近になってもよく学校の夢を見る。たいていは、宿題やってなくて困ったとか、試験勉強しないといけないけどやりたくなくて困ったとか、そういう夢を見る。その当時の同級生が出てきたり、なぜかいまの同僚が出てきたりする。けどたいてい、困っている。

仕事をし始めてよいことのひとつは、宿題や試験に追われることがなくなったことで、家に帰ればのんびりできる。もちろん勉強したりもするけど、それは趣味のようなものだから気にならない。僕は不真面目な人間に生まれたようで、宿題とか試験勉強ができない質のようである。

ところで働き出して2年くらいだけど、その間にまだ1回しか帰省していなかった。ので明日、ちょっと遅い夏休みを取って帰省します。

お土産買ったので楽しみにしていてください。

Android Studio便利テク #3 — メソッドをグルーピングする

Javaでクラスの実装を進めていくと、あるメソッドが継承元クラスのメソッドをオーバーライドしているのか、あるいは何らかのinterfaceの実装なのか、だんだん見分けがつかなくなります。一定の規則でメソッドを並べたり様々な工夫があることと思います。


Xcodepragma mark

#pragma mark - UITableViewDelegate

iOSアプリ開発に慣れていれば、上記のような#pragma markを残しておく習慣があることでしょう。ちなみにSwiftでは以下のようになります。

// MARK: - UITableViewDelegate

region

Android Studioにはpragma markとは少し違いますが、regionというコメントの書き方があります。

    //region GoogleApiClient.ConnectionCallbacks
    @Override
    public void onConnected(Bundle bundle) {
        connectLocationService();
    }

    @Override
    public void onConnectionSuspended(int i) {
        disconnectLocationService();
    }
    //endregion

上記のように//region//endregionの間に囲まれた範囲を、任意の名前で定義することができます。この例であれば、二つのメソッドGoogleApiClient.ConnectionCallbacksインターフェースの実装であることが明白です。

f:id:cockscomb:20140813230713p:plain
Surround Withで選択範囲を囲う

f:id:cockscomb:20140813230732p:plain
//regionコメントで囲まれている

またこのregionの範囲はフォールディングできます。

f:id:cockscomb:20140813230747p:plain
region部分がフォールディングされている

ちなみに//regionの書き方はVisual Studio風ですが、NetBeans<editor-fold desc="GoogleApiClient.ConnectionCallbacks">``</editor-fold>という書き方もできます。


本質的には、クラスにメソッドが増え過ぎて迷子になるようなら、役割が広すぎるクラスになってしまっているのかもしれません。そのような場合でもコメントなどによって適切なグルーピングが行われていれば、リファクタリングの助けになるでしょう。いずれにせよ、読みやすくコードを整理することはよい習慣です。

プロの力が身につく Androidプログラミングの教科書

プロの力が身につく Androidプログラミングの教科書