dip Engineer Blog

Engineer Blog
ディップ株式会社のエンジニアによる技術ブログです。
弊社はバイトル・はたらこねっとなど様々なサービスを運営しています。

Bridging HeaderをはずしたらUIKitが解決できなくなった!

はじめに

こんにちは。iOSエンジニアの@satoshi-babaです。 いま巷で賑わっているXCodeGenを検証する過程で、UIKit系のクラスの参照が解決できない事象に出くわしました...。 その事象を解決するまでの道のりを共有したいと思います。

事の始まり

現在、私はXCodeGenの検証を実施しています。

ある日私はほとんどの設定を書き終え「いや〜これは完璧だわ!ビルドして動作確認するぞ!」と息巻いていたところ、 およそ1000を超えるSwift Compiler Errorに遭遇してしまいました。

表示されていたエラーは大きく分けて以下の3つでした。

  • Use of Undeclared Identifier CGFloat
  • Use of Undeclared Identifier UIFont
  • Use of Undeclared Identifier UIImage

該当の処理を確認すると、確かにCGFloatやUIFontは使用されています。 しかしimportされているのはFoundationのみで、UIKitに属するCGFloatやUIFontは解決できなそうです。

import Foundation
extension String {
    func labelHeight(width: CGFloat, font: UIFont, maxLine: Int = 0) -> CGFloat {
        let label = UILabel()
        label.font = font
        label.lineBreakMode = .byTruncatingTail
        label.numberOfLines = maxLine
        label.text = self
        let rect: CGSize = label.sizeThatFits(CGSize(width: width-label.layoutMargins.left-label.layoutMargins.right, height: CGFloat.greatestFiniteMagnitude))
        return rect.height
    }
}

とりあえず全てのクラスにUIKitのimportすれば動きそうです。 しかし、なぜこのような状態で今までコンパイルできたのか、XCogeGenで生成したプロジェクトで解決できなくなったのか気になります。 もしかしたら重要な見落としがあるかと思い、調査することにしました。

原因はBridging Header忘れ!!

XCogeGenで生成したプロジェクトの時に発生する問題です。絶対に設定し忘れている項目があるはずです! Build Settingsを上から順番チェックしてみることにしました。

すると見事にBridging Headerの追加を忘れていました! f:id:satoshi-baba:20200213142343p:plain

設定を追加したら無事にビルドができるようになりました。 これで安心!...では終われません!

Bridging Headerの動きをさらに追ってみることにしました。

Bridging Headerは全てのSwiftファイルにimportされる

まずはBridging Headerの動作について、下記の公式ページで確認してみました。 Importing Objective-C into Swift

どうやらBridging Headerは全てのSwiftファイルにimportされるみたいです。 Bridging Headerまたはその先でUIKitをimportしていればいい感じに解決されちゃいそうですね...!

実際に読み込んでいる先でimportされていました!

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface HogeLogic : NSObject
(省略)

感想

Bridging Headerをはずすだけでこんな影響が出るなんて思いもしませんでした。 昔のC言語でのCommonヘッダーみたいな役割が簡単にできちゃいますね!(意図してませんでしたが) もしかしたらコードレビューの観点に盛り込むべきかもしれませんね。

著者

dippeople.dip-net.jp