Edited at

Swiftでメモ的なwarningの発生のさせ方(Objective-Cの#warning相当)

More than 1 year has passed since last update.

Objective-Cでは#warning 何かメモとコード中に書くことによって、明示的に警告を発生させることが出来ました。

Screen Shot 2015-08-17 at 10.50.15 AM.png

きっと、たぶん、おそらく、めいびー: 「あとでやろう」ってときは #warning hoge

これを埋め込んだ状態で、コミットや特にPUSHはするべきじゃ無いですが、開発中に手元の状態を一時的に変えたい時や、ファイルを行ったり来たりするときのブックマークとして便利でかなり活用していました。

ただ、Swiftコードではこのやり方が出来ず1、不便だなと思っていましたし、それが原因のミス(一時的に手元で弄って後で戻すつもりのものをコミットしてしまうなど)も発生したりでけっこう困っていました。

というわけで解決策です。


【2018/04/19追記】Swift 4.2以降の#warning命令を活用

コードに#warning("XXX")を書けば警告扱い、#error("XXX")を書けばエラー扱い、とObjective-Cと同様な表現をできるようになります。

(本記事を書いた時点ではこの命令が存在せずその予定もありませんでした。)

というわけで、Swift 4.2以降であればこれで解決です( ´・‿・`)


【2017/04/20追記】realm/SwiftLint を利用

SwiftLintを導入すると、"\\b(?:TODO|FIXME)(?::|\\b)"のパターンにマッチする文字列がソースに含まれていると警告発生させてくれる機能がデフォルトで有効になっています。

https://github.com/realm/SwiftLint/blob/3f880432c3e5a1379f2020f7a47d2518919b1f92/Source/SwiftLintFramework/Rules/TodoRule.swift#L89

少し前までは、TODOに記載したメッセージが警告文に含まれず若干使いにくかったですが、 https://github.com/realm/SwiftLint/pull/765 の改善で良い感じの表示になりました🎉

Screen Shot 2017-04-20 at 14.50.47.png


以下、Swift 4.2より前のバージョンかつSwiftLintを使わない場合のやり方です。


方法1: 適当な警告を発生させるような短いコードを置く

初め、こんなスニペットを用意しておくと良いなと思いました。

(警告発生用のコードとしては、もっとベターなものがあるかもです。)

if false { "<#note: String#>" }

Screen Shot 2015-08-17 at 10.55.01 AM.png

一覧上で、内容が見られないのが微妙ですかね。


方法2: availabilityを活用した警告発生用の関数を用意

あるいは、方法1と似たものとして、こんな関数を用意というのも良いですね。

@availability(iOS, deprecated=1.0, message="**WARN** (not deprecated)")

public func WARN(note: String) {
log.severe(note)
}

Screen Shot 2015-08-17 at 11.40.47 AM.png

FIXME関数の中身は空でも良いですが、ロガーを使って、目立つ出力がされるようにしてみました。

→【追記】ログの呼び出し箇所表示がWARN関数自体になって微妙ですね。

Screen Shot 2015-08-17 at 11.43.00 AM.png

方法1と違って、スニペット用意せずとも補完付きで打てる点が嬉しいです。


方法3:

Build Phasesに以下のスクリプトをRun Script Phaseとして挟み込むことで抽出。

KEYWORDS="WARN:"

find ${SRCROOT} \( -name "*.h" -or -name "*.m" -or -name "*.swift" \) -print0 | \
xargs -0 egrep --with-filename --line-number --only-matching "($KEYWORDS).*\$" | \
perl -p -e "s/($KEYWORDS)/ warning: \$1/"

Screen Shot 2015-08-17 at 11.08.07 AM.png

Xcode4のTODOタグを警告に出力する - 中継地点をアレンジしたものです。

(Swift対応と、対象をWARNに限定しただけで、それ以外はそのまま使っています。)

初めは方法1を思いついて、まあ手元の一時的な対応しては悪く無いかなと思いつつ、他に探していたらこちらの方法見つけました。

こちらの方が正攻法な気がしますね。

実行時間気になりましたが、ある程度大きなプロジェクトでも1秒未満だったので気にせず良さそうです。


警告検知を早める

コードの状態にも寄りますが、方法3だとビルド開始後、検知までけっこう時間かかったりします。

Run Scriptsの順番をきちんと前の方(Check Pods Manifest.lockの前)に持ってくれば、わりと早く検知してくれます。

Xcode上でBuild Phasesのところの項目をドラッグ&ドロップで移動出来るはずですが、バグなのかなかなか移動してくれなかったので、project.pbxprojファイルを直接弄って先頭に持ってきました(´・︵・`)


project.pbxproj

buildPhases = (

FEC167B61B8174A000368FE6 /* Output Warnings */,
9C1E5A4F082E70034C31F9D2 /* Check Pods Manifest.lock */,
1305C9B91A24E5F700DA30D7 /* Sources */,
1305C9BA1A24E5F700DA30D7 /* Frameworks */,
1305C9BB1A24E5F700DA30D7 /* Resources */,
9424C1A7DF62DEB9FB41A14A /* Copy Pods Resources */,
FE2524711A87511600814222 /* Embed Frameworks */,
FEE3798A1A9A696E00D4268B /* Update Setting */,
FE56F4601AA9280E00852713 /* Carthage */,
FE9593401B08575A00951031 /* Crashlytics */,
);


方法3の利点


  • 一覧に適切なメッセージが表示される

  • コード上のどこにでも埋められる


    • 方法1・2だと、if文書けないところ(例えばファイルトップレベル)には置けない



ざっと使ってみた感触だと、方法3がベストですかね。

方法2もまあまあ良いと思いました。

方法1は悪く無いですが、方法2に勝る点が無いので微妙ですね。

とりあえず、方法2・3適当に使いながらしっくり来る方選ぼうかなと思います( ´・‿・`)


参考





  1. https://qiita.com/mono0926/items/6fee3e5eac068a84f462#20180419追記swift-42以降のwarning命令を活用 に記載の通りSwift 4.2からは同等の書き方ができるようになりました。