togo

= ひとりごと to go

zumuya の人による机の上系情報サイト

Sandbox に悩まされることばかり

  • Apple
  • 開発

6 月から Mac App Store のアプリケーションは Sandbox 化が必須になったけど、最近アプリケーションを作っていて悩むのはほとんどその Sandbox 関係だ。

PubSub.framework

RSS のフィードを扱いやすくしてくれる、Leopard で追加されたフレームワーク。今のところ Safari や Mail で使われている。

Lion になっても 1 つの PubSubAgent プロセスを複数アプリケーションで共有する仕組みが維持されていて Sandbox と相性が悪そうだ。と考えていたら本当に動かなかった。

しばらく調べて“Sandboxing the PubSub framework”という記事を発見。知りたいことがすべて書いてある。.entitlements ファイルの中身が temporary-exception だらけになってしまうのが悲しいけれども。

このフレームワーク、MobileMe のときは複数 Mac で未読フラグなどを同期してくれたのだけど、iCloud になってからは同期されなくなってしまったのが残念。最近は目立った改良もなく Apple もあまり力を入れていないようなので、この先どうなるのか将来性が不安。
それでもほとんどコードを書かずに RSS の取得/構文解析/登録を行うことができる優れものなのだ。

2013.12.8 追記:PubSub は Mavericks で見事に deprecated!自分が使わなくなったフレームワークは廃止する、それが Apple。

ログイン項目に登録 ヘルパーをログイン時に開く

多くのアプリケーションでは“ログイン時に開く”というチェックボックスがあってそれをクリックするだけでログイン項目の登録/削除ができるのだけど、Sandbox ではこれまでの LSSharedFileListInsertItemURL() を使った方法が使用できない。

解決策は Stack Overflow の“How to create a helper application for Mac App to start it on user login?”という質問に書いてある、SMLoginItemSetEnabled() を使った方法。
ただしアプリケーション自身を登録することはできず内包するデーモンのみ登録可能で、これまでのようにシステム環境設定の“ログイン項目”のところには表示されないという違いがある。

  1. Info.plist に LSUIElement を追加したヘルパーアプリケーションを用意。
  2. ヘルパーは親アプリケーションパッケージ内の Contents/Library/LoginItems/ に置くようにする。
  3. 親アプリケーション:LSRegisterURL() でヘルパーの URL を登録。
  4. 親アプリケーション:SMLoginItemSetEnabled() にヘルパーのバンドル ID を渡す。

この方法で開かれるのはヘルパーアプリケーションなので、これまでの代替にならない場合もある。「ヘルパーアプリケーションの中で親アプリケーションを開けばいいのでは?」と考えたが、Sandbox に弾かれてしまう。

アプリケーションを再度開く

自動アップデートの仕組みを提供する Sparkle で新バージョンをダウンロードしたあとにインストール・終了してから再度開く仕組みがあったけど、あれはアプリケーションを起動するためだけのプロセスを用意しておき、それを起動してからアプリケーションを終了することで実現している。

Sandbox を有効にすると、用意したプロセスの起動までは成功。だが“ログイン時に開く”の件と同様、そのプロセスから親アプリケーションを開くところで弾かれてしまう。

成功例を探したところ、LaunchAtLoginHelperというものを発見。ソースを読んでみると...

  1. 親アプリケーションの Info.plist で独自の URL スキームを定義しておく。
  2. ヘルパーでそれを使用した URL を開き、親アプリケーションを起動。

なんと URL スキームを使っていた。Apple が推奨しているのかは知らないけど iOS ではよく見かける。こんなところも Back to the Mac なのか...

Share

リンクも共有もお気軽に。記事を書くモチベーションの向上に役立てます。