“Swiftize”という謎単語を思いつきました。
僕の作っているiOS用アプリは大部分がObjective-Cで書かれています。もちろん新たに追加する部分はSwiftで書いているので、全体の2, 3割がSwiftで書かれているでしょうか。それでSwiftのバージョンが上がるたびに派手にエラー・警告が吐かれるという罰ゲームを受けています。
仕様変更しすぎでは。。。
仕様変更しすぎでは。。。
そんなことからObjective-Cで書かれた処理をあえてSwiftで書き直すのは、まだ時期尚早なのでは、と手をつけていませんでした。でも、ひとつのプロジェクトでSwiftとObjective-Cが混ざった状態というのは、著しく生産性が落ちるのです。頭がパッパと切り替わらないのです。おっさんなのです。
今から思えば、中途半端に混ぜるようなことはしないで、一気に書き換えるようにすれば良かったなぁ。
今から思えば、中途半端に混ぜるようなことはしないで、一気に書き換えるようにすれば良かったなぁ。
でもSwiftもバージョン3になりましたしね、ここは一念発起して少しづつ"Swiftize"していこうと決めました。
そこで、どうせなら綺麗なソースを書きたいので、SwiftLintを導入することにしました。
SwiftLint本体はHome Brewでインストールしました。
$ brew install swiftlint
==> Downloading https://homebrew.bintray.com/bottles/swiftlint-0.16.1.sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring swiftlint-0.16.1.sierra.bottle.tar.gz
🍺 /usr/local/Cellar/swiftlint/0.16.1: 37 files, 13.6M
$ swiftlint version
0.16.1
$
2. Build Phasesで”+”をクリックします。
3. New Run Script Phaseを選びます。
4. Run Scriptが追加されるので、開きます。
5. Swift LintのREADME.mdにある、シェルスクリプトをコピペします。
if which swiftlint >/dev/null; then
swiftlint
else
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi
6. プロジェクトのディレクトリに、.swiftlint.ymlを追加してLintのルールをカスタマイズします。
$ cd HelloSwiftLint/
$ ls -la
total 8
drwxr-xr-x 7 foobar staff 238 2 3 04:02 .
drwxr-xr-x 8 foobar staff 272 2 17 00:09 ..
-rw-r--r-- 1 foobar staff 1465 2 3 04:02 .swiftlint.yml ←これを追加します
drwxr-xr-x 7 foobar staff 238 2 2 03:03 HelloSwiftLint
drwxr-xr-x 5 foobar staff 170 2 2 02:42 HelloSwiftLint.xcodeproj
drwxr-xr-x 4 foobar staff 136 2 2 02:49 HelloSwiftLintTests
drwxr-xr-x 4 foobar staff 136 2 2 02:49 HelloSwiftLintUITests
$
.swiftlint.ymlの中身は、やはりREADME.mdをお手本にして修正を加えます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
disabled_rules: # rule identifiers to exclude from running | |
- line_length #1行の長さ | |
# - comma | |
# - control_statement | |
opt_in_rules: # some rules are only opt-in | |
- empty_count | |
- missing_docs | |
# Find all the available rules by running: | |
# swiftlint rules | |
included: # paths to include during linting. `--path` is ignored if present. | |
- HelloSwiftLint | |
excluded: # paths to ignore during linting. Takes precedence over `included`. | |
- HelloSwiftLint/FooBar | |
- Pods | |
# configurable rules can be customized from this configuration file | |
# binary rules can set their severity level | |
force_cast: warning # implicitly | |
force_try: | |
severity: warning # explicitly | |
# rules that have both warning and error levels, can set just the warning level | |
# implicitly | |
line_length: 256 | |
# they can set both implicitly with an array | |
type_body_length: | |
- 300 # warning | |
- 400 # error | |
# or they can set both explicitly | |
file_length: | |
warning: 500 | |
error: 1200 | |
# naming rules can set warnings/errors for min_length and max_length | |
# additionally they can set excluded names | |
type_name: | |
min_length: 4 # only warning | |
max_length: # warning and error | |
warning: 40 | |
error: 50 | |
excluded: iPhone # excluded via string | |
variable_name: | |
min_length: # only min_length | |
error: 4 # only error | |
excluded: # excluded via string array | |
- id | |
- URL | |
- GlobalAPIKey | |
reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, junit, html, emoji) |
included:にはチェックするソースへのPATHを指定します。
これはプロジェクトの直下にある、プロジェクトと同名のディレクトリを指定すればいいと思います。(これを指定しないとプロジェクトの下全部が対象になるのかな? そんな感じがするんだけど)
excluded:には逆にチェックしたくないファイルへのPATHを指定します。
CocoaPodsを使用しているならPodsとか。あと、include:で指定した下に、何か外部のライブラリを置いたような時、それを除外するよう指定できます。
ルールのカスタマイズとは言っても、特別なことはしていません。ただ、デフォルトではかなり厳しいチェックが行われますので、ルールを少し緩めています。
disabled_rules:には、チェックしない項目を指定します。
ここには1行の長さをチェックしないように追加しました。ご存知のように、AppleのAPIはのけぞる長さですからね。
type_body_length:は1個の型の定義(クラスとかね)の行数、file_length:は1ファイルの行数です。
これは適当に大きめに変更します。ただ、ソースにルールを合わせたのでは、本末転倒になりますからほどほどに。
type_name:は型名(クラスとか)の長さ、variable_name:は変数名の長さです。
型名はともかく、変数名は1文字から使いたいのでmin_length:は指定なしにしてあります。
あ、 gitを使っているなら、.gitignoreに.swiftlint.ymlを追加しておくのもいいですよ。
(省略)
#Swift Lint
.swiftlint.yml
( 省略)
6. .swiftlint.ymlができたら、 プロジェクトを開いてビルドします。
![]() |
警告が、だばぁ〜 |
7. ワーニングが山ほど出ますので、涙をこらえながら、ひとつひとつ修正していきます。
ちょっと気になったのは、警告対象の箇所を修正しても、警告を示す黄色の表示が消えないことがあったことです。開いているのとは別のファイルに警告が残っているときに、その警告が開いているファイルに表示されるということが、しばしば起こるようです。
修正したのに警告表示が消えないなぁ、というような時は一旦そのファイルを閉じて、Xcodeの左の問題ナビゲーターに表示されているワーニングメッセージをダブルクリックして、その警告が指しているSwiftファイルを開きなおすと、うまく問題の箇所に黄色の表示が現れると思います。
※2017/05/16追記
この不具合はSwiftLintをバージョン0.18.1に更新したら起きなくなりました。どうやら修正されたようです。
正直、Lintが指摘する書き方に対して、「えー、そこはこう書くだろぉ〜、普通ぅ〜」というようなことは、ままありますが、そんなもん慣れです。その書き方に慣れてさえしまえば、ちょっとした書き違い(間違いじゃなくて)がなくなって、可読性がよくなります。こういうことの積み重ねがバグの少ないプログラムに繋がっていくんだろうな、って思ってます。
、、、たぶんね(白目)。
しかしSwift、もう少しコンパイルが早くなりませんかね?「凛としてSwift (血闘編ノ壱)」に続きます。
♪♪♪
こちらもどうぞ。
凛としてSwift (血闘編ノ壱)
凛としてSwift (血闘編ノ弐)
凛としてSwift (血闘編ノ参)
帰ってきた凛としてSwift(くるくる編)