OSX アプリでカスタムフォントを使う

Cocoa/Swift プログラミング

初めてまともに作った OS X アプリを @koogawa さんにテストしてもらったところ、いきなり画面に何も表示されない不具合に見舞われました。

原因はカスタムフォントの読み込みミスだったので、改めて正しい組み込み方を整理しておくことにしました。

発端

OS X アプリを作って @koogawaさん にアプリを使ってもらおうとしたところ、画面に何も表示されない不具合に見舞われてしまいました。

システムログを調べてもらったところ、次のログが出力されていることが分かりました。

Failed to set (contentViewController) user defined inspected property on (NSWindow): *** -[NSTextView setFont:]: nil NSFont given.

今回のアプリでは、バンドルにカスタムフォントを含めて使うようにしたつもりだったんですけど、どうやらバンドルからフォントを読み込むことができていなくて、戻り値で得られた nil をそのまま NSTextViewfontプロパティ に代入したことが、画面全体が描画されない原因につながっていた様子でした。

フォントを取得できたときにだけ設定する

そこでまずは、なんらかの事情でフォントが取得できなかったとしても、適切に画面描画が行われるように修正します。

とは言ってもなにも難しいことはなく、バンドルからフォントを読み込んで nil が得られたときに NSTextView にフォントを設定しないようにします。

if let font = SystemFont.FontForCode.fontWithSize(15.0) {

	self.codeTextView.font = font
}

今回は SystemFont型fontWithSize:メソッド で、フォントが得られたらそれを、得られなければ nil を返すようにしてあるので、ちゃんとフォントが得られたときだけ NSTextView にフォントを設定します。

OS X アプリでバンドル内のフォントを使う

バンドルにカスタムフォントを含める

OS X アプリで、バンドル内にカスタムフォントを含めてアプリで使えるようにするには、まず、フォントデータを収めるリソースフォルダーを決めて、それを Info.plistApplication fonts resource path (ATSApplicationFontsPath ) に記載しておく必要がある様子でした。

<key>ATSApplicationFontsPath</key>
<string>Fonts</string>

ビルドフェイズでフォントをバンドルにコピーする

そうしたら、プロジェクト内にフォントファイルを保存して、それを Copy Files ビルドフェイズを作って Resources フォルダー内の先ほど指定したフォルダーにコピーされるようにします。


Copy Files ビルドフェイズは、アプリのターゲット設定の Build Phases 画面にある +ボタン から行えます。

ここで Copy Files Phase を選択して、作成された Copy Files フェイズを、既存の Copy Bundle Resources フェイズの次あたりに移動します。

そして作成した Copy Files ビルドフェイズは、次の内容を設定します。

項目
Destination Resources
Subpath Fonts
Copy on when installing (チェックしない)

設定項目の下にあるリストには、上記で指定した場所 (Resources/Fonts にコピーするファイルを追加します。今回は、プロジェクトに追加しておいたカスタムフォントのファイルを指定することになります。

バンドルに含めたフォントを使う

ここまでできたら、これでバンドル内のフォントを OS X アプリ内で使えます。

let font = NSFont(name: "SourceCodePro-Regular", size: 10.0)!

フォント名にはファイル名でなく、フォントに割り当てられている PostScript 名 を指定します。この名前は OS X に付属の FontBook アプリで確認できます。