面白きことは良きことなり

拙く未熟なiOSエンジニアの備忘録と戯言

Xib(Nib)上で設定したfontの種類やサイズが適用されなくて困った話

遭遇した問題

とあるプロジェクトでXib上に配置したUILabelに対して、Xib上からfontの種類とサイズを変更した。
しかし実機上で確認しても、そのfontの変更は適用されていなかった。

原因

何が問題だったかというと、application(_ : launchOptions: ) -> BoolUILabel.appearance().font = UIFont(name: "System", size: 15.0) のようなことをしていた。

この appearance() は初めて知ったのだけど、説明は以下。

public protocol UIAppearance : NSObjectProtocol {

    /* To customize the appearance of all instances of a class, send the relevant appearance modification messages to the appearance proxy for the class. For example, to modify the bar tint color for all UINavigationBar instances:
        [[UINavigationBar appearance] setBarTintColor:myColor];
     
        Note for iOS7: On iOS7 the tintColor property has moved to UIView, and now has special inherited behavior described in UIView.h.
        This inherited behavior can conflict with the appearance proxy, and therefore tintColor is now disallowed with the appearance proxy.
      */
    public static func appearance() -> Self

...

appearance()で生成したclassのinstanceで行なった処理は、そのclassのinstance全てに対して同じ振る舞いをさせるもの。

Xibとか関係なくinstanceの設定が上書きされてしまうので、Xib上の設定は意味がなくなってしまう。

解決策

  • 可能なら appearance() 使ってるコードは削除する
  • コード設定し直す (今回で言えば、 UIFont(name:size:) を使ってfontを再設定する)

そもそも…

ダメ、ゼッタイ

  • 汎用的なUIKitのclassに appearance() は使うべきじゃない
  • appearance() 使うなら継承したclass等限定的に使われるもののみ
  • コードonlyなプロジェクトなら汎用的なUIKitのclassに使うのもありとは思う

これに関しては、Xibに限らずStoryboardでも例外なく発生するもののため、注意が必要。
自分はテスト用のプロジェクト作って調べまくったけど、再現しなくて分からず最終的に苦肉にも // 原因不明だけどXibで設定した内容が反映されないため、コードで設定 のようなコメントを残すことになった。
タスク完了した後、原因を知りフザケルナという気持ちになった。やるせない。

自分の無知故な部分もあるけど、コード書いた人は後に及ぼす影響を想像できなかったのだろうか…