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

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

![Screen Shot 2015-08-17 at 10.50.15 AM.png](https://qiita-image-store.s3.amazonaws.com/0/19398/eb884361-369b-5ca1-9fdf-38155b5eda65.png)

[きっと、たぶん、おそらく、めいびー: 「あとでやろう」ってときは #warning hoge](http://aimai4.blogspot.jp/2012/09/warning-hoge.html)

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

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

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

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

コードに`#warning("XXX")`を書けば警告扱い、`#error("XXX")`を書けばエラー扱い、とObjective-Cと同様な表現をできるようになります。
(本記事を書いた時点ではこの命令が存在せずその予定もありませんでした。)

- [swift-evolution/0196-diagnostic-directives.md at master · apple/swift-evolution](https://github.com/apple/swift-evolution/blob/master/proposals/0196-diagnostic-directives.md)
- [Forcing Compiler Errors in Swift — Erica Sadun](https://ericasadun.com/2018/04/18/forcing-compiler-errors-in-swift/)

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

# 【2017/04/20追記】[realm/SwiftLint](https://github.com/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 の改善で良い感じの表示になりました🎉

<img width="595" alt="Screen Shot 2017-04-20 at 14.50.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/19398/486fb330-fccb-aa2f-f951-3114e6edcf88.png">


---

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

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

初め、こんなスニペットを用意しておくと良いなと思いました。
(警告発生用のコードとしては、もっとベターなものがあるかもです。)

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

![Screen Shot 2015-08-17 at 10.55.01 AM.png](https://qiita-image-store.s3.amazonaws.com/0/19398/be1c9879-4b8d-cea7-66db-18491d22ca86.png)

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

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

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

```swift
@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](https://qiita-image-store.s3.amazonaws.com/0/19398/b2a6da68-74c6-63c7-0672-f1cc674c94c6.png)



`FIXME`関数の中身は空でも良いですが、ロガーを使って、目立つ出力がされるようにしてみました。
→【追記】ログの呼び出し箇所表示が`WARN`関数自体になって微妙ですね。

![Screen Shot 2015-08-17 at 11.43.00 AM.png](https://qiita-image-store.s3.amazonaws.com/0/19398/7c4b9581-13d1-6e24-c6a3-00765b705de2.png)


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

# 方法3: 

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

```sh
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](https://qiita-image-store.s3.amazonaws.com/0/19398/f82f234e-5a68-6bc6-7c29-70c87f3a30d1.png)



[Xcode4のTODOタグを警告に出力する - 中継地点](http://d.hatena.ne.jp/h_mori/20110720/1311190752)をアレンジしたものです。
(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適当に使いながらしっくり来る方選ぼうかなと思います(　´･‿･｀)

# 参考

- [Xcode4のTODOタグを警告に出力する - 中継地点](http://d.hatena.ne.jp/h_mori/20110720/1311190752)
    - Swiftではなく、Objective-CのTODOコメントを警告一覧に表示したい、という内容
- [Swift: #warning equivalent - Stack Overflow](http://stackoverflow.com/questions/24183812/swift-warning-equivalent)
    - この記事書いている途中に見つけた解決策で、内容はほぼ一緒です。
    - 本Qiita記事では、それぞれスクリーンショット貼ったり、どれが良いか比較したりしているので、また別の価値はあると思います。

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