Xcode 6では、OS X用アプリケーションの開発にStoryboardが使えるようになりました。iOS用のアプリケーション開発ではもうお馴染みですね。OS Xもこれからはxibではなく、Storyboardの方に新機能が追加されていくんでしょう、きっと。
実際にStoryboardを使ってアプリケーションを作ってみたのですが、そのときにハマった罠があったので解決方法と合わせて紹介します。
- ハマったこと
- windowのcontentViewControllerのviewを変更すると、windowのframeのautosaveが効かなくなる。
- 解決方法
- windowのcontentSizeと、contentViewControllerのviewのsizeを一致させる。
WindowのFrameのAutosaveとは
アプリケーションが開いているウインドウのframe(位置、大きさ)が変更されるたびに、最新のframeの値を保存してくれる機能です。加えて、アプリケーションの起動時には、保存されている設定値をもとにウインドウのframeを再現してくれる機能でもあります。
この機能を有効にしておくことで、ユーザがアプリケーションを一旦終了したあと、次に同じアプリケーションを開いたときにも前回のウインドウのframeが再現されます。
ウインドウを常にたくさん開き、アプリケーションも起動したり終了したり頻繁にする私のようなユーザにとってはたいへん嬉しいことです。
有効化する方法
InterfaceBuilderを使った有効化は簡単です。windowを選択した状態で、
Autosave(Autosave Name)を入力すれば完了(※1)です。
罠にハマる手順の一例
Autosaveの有効化自体は簡単ですが、いつの間にかAutosaveが効かなくなる、という罠にハマりました。この罠にハマったときの手順を紹介します。
- Storyboardを使用して新規アプリケーションを作成する
- windowのautosaveを有効化する
- アプリケーションを実際に起動し、windowのautosaveが有効化されていることを確認する(ヨッシャ)
- contentViewControllerのviewを編集する
- ボタンを置く
- auto layoutを追加する、など
- いろいろ編集する
- いろいろ編集し終わったのでアプリケーションを実際に起動してみる
- ア...レ...? auto...saveガ...キイテ......イナイ!?
- 焦る
解決策
原因を切り分けるため、機能を絞り込んで調査した結果、viewControllerのviewのsizeが変更される(を変更する)とautosaveが期待通りに動かなくなることがわかりました。
windowのcontentSizeと,viewのsizeを一致させましょう。
原因
いまのところ、今回の解決策で間に合っているのでそれ以上には詳しく調べていません。windowのframeを復元する処理と、windowのsizeをviewに合わせる処理が衝突して、復元に失敗してしまうのかな、と考えています。
Storyboardを使うと罠にハマる理由
従来のxibファイルを使った手順では、viewはwindowに直接貼られていたので、たいていどんな操作をしてもwindowとviewのサイズは常に同期するようになっていました。そのため、今回の罠にハマることがなかったようです。
一方、新しいStoryboardを使った手順では、テンプレート上にwindowControllerとviewControllerがあらかじめ用意され、それぞれのシーンは綺麗に分離されています。windowのsizeとviewのsizeはInterfaceBuilder上で強制的に同期されることはありません。それにより、windowとviewのsizeの不一致が発生することになり、今回紹介した罠にハマりやすくなっています。
※1
Autosaveは、Autosave Nameに設定された名前をkeyとして、User Defaults を使って保存/復元を行います。そのため、Autosave Name は各ウインドウで重複しないように注意する必要があります。
なお、windowにはRestorableという別のオプションがありますが、このON/OFFは今回紹介しているAutosaveの機能には影響がありません。