【part 2】AppApp のリファクタリング過程紹介【SwiftLint導入後のError解消編】

どうも。Reoです。

前回「AppApp のリファクタリングを始めます!【SwiftLint 導入編】」から始まったAppAppのリファクタリング過程紹介の第2弾です。

作業をする時は常に WordPress を開いて、むしろブログを書くことをメインにしながらやっていく予定です。

しばらくは何も考えずブログを書きながらリファクタリングするマシーンになります。仕事が入ればそっちを優先しますが…

 

環境

  • Xcode11.3.1
  • Swift 5.1.3
  • iOS13.3

前回 → AppApp のリファクタリングを始めます!【SwiftLint 導入編】

リポジトリは uruly/AppApp にて公開しています。

 

今回の目標

今回の目標は、SwiftLint の Warning と Error をなくすぞ!!!です。

黙々と作業をして、記事に書くことが特にないじゃんと思っていますが、まぁ何かしら書きます。今回は特に有益になりそうなものもないかもしれないです。

なんやかんやで書き終わってみると、長くなってしまったので今回は Error 解消だけになりました。

 

.swiftlint.ymlの中身

前回の最後に、disabled_rules に force_try を追加した状態になっています。後々有効化させるかもしれませんが、そこまで頑張れるか…

disabled_rules:
  - force_cast
  - force_try

included:
  - AppApp

excluded:
  - Carthage

line_length: 200
large_tuple: 5

file_length:
  warning: 500
  error: 1200

nesting:
  type_level:
    warning: 2

identifier_name:
  excluded:
    - id
    - URL
cyclomatic_complexity: 20

 

都度追加するかもしれないですし、しないかもしれないです。

 

Errorを潰そう!

SwiftLint を導入したことによって発生した Error を修正していきます。
合計10個なのでサクッといきたいけどちゃんと書くよ。

 

Identifier Name

Identifier Name Violation: Variable name should be between 3 and 40 characters long: ‘r’ (identifier_name)

変数の名前は3〜40文字の間で設定しなさぁ〜い!ってやつです。

怒られている場所晒し。例えばこういうところ。

extension UIImage {

    func maskCorner(radius r: CGFloat) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(self.size, true, 0.0)
        let rect = CGRect(origin: CGPoint.zero, size: self.size)
        UIBezierPath(roundedRect: rect, cornerRadius: r).addClip()
        draw(in: rect)
        let clippedImage = UIGraphicsGetImageFromCurrentImageContext()

        UIGraphicsEndImageContext()
        return clippedImage
    }
}

if文も対象ですね。

for i in order ..< objects.count {
    try! realm.write {
        objects[i].order = i + 1
        realm.add(objects[i], update: .all)
    }
}

座標を示すx, y も対象です。

func scrollToHorizontallyCenter(index: Int, x: CGFloat) {
}

これって結構 Swift 特有だと思いませんか?

他の界隈にいると、当たり前のように i や x, y が登場してきます。

先日読んだJavaScriptの本でも当然のように出てきましたし、プログラミングをやっていて当たり前のようにi, j, x, y は出てきます。計算が多いと特にそうですね。

でも個人的にはこのルールは好きです。

むしろ他言語にいくと読めづらいと思ってしまいますね。

 

修正していきますね。

① -> r 部分を削除してそのまま radius にする。(なんで r にしたのかもちょっと謎)


    func maskCorner(radius: CGFloat) -> UIImage? {

 

② -> for 文を使わないで書けないかをまず考えます。

try! realm.write {
    objects.map { object in
        // 変更した order より大きいものだけ並び替える
        if object.order > order { return }
        let newObject = object
        newObject.order += 1
        realm.add(newObject, update: .all)
    }
}

そもそものRealmの使い方と実装がアレなのでチョットなんともいえないんですが、map等を利用してfor文自体をあんまり使わないようにするといいはず。と思っています。いや、この部分難しいな。

あとは for i in ..&lt; hoges.count {} よりも for hoge in hoges {} を使おうって話かもしれないです。

いやいや配列の添字がほしいんじゃって時はよくあるので、そういう時は enumerated を使うと良いです。

for (index, object) in objects.enumerated() {}

便利!!!でも実際に使ったことってあんまりないかも。

 

③ -> x を何のxなのかを明確にする。targetX に変更しました。

func scrollToHorizontallyCenter(index: Int, targetX: CGFloat) {
}

 

Shorthand Operator

Shorthand Operator Violation: Prefer shorthand operators (+=, -=, *=, /=) over doing the operation and assigning. (shorthand_operator)

複合代入演算子を使いましょうね〜ということ。

// 修正前
label.order = label.order - 1
// 修正後
label.order -= 1

うむ。

 

Identifier Name(2回目)

またこれだ!

Identifier Name Violation: Variable name should only contain alphanumeric characters: ‘APPLE_ID’ (identifier_name)

アプリ全体の定数みたいなのを以下のようにしてたんですねぇ。


let APPLE_ID = "1319908151"

しかも結構雑に。適当なファイルに書いてるんですよねー。

これは共通の定数を各ファイルを用意(Constants.swift)して、以下のように書きました。

import UIKit

extension String {

    static let appleID = "1319908151"
}

extension UInt64 {

    static let schemaVersion = 5
}

 

これで使う時は String.appleID もしくは .appleID で使えます。

 

単純な名前変更ではないので、VSCode でフォルダごと開いてまとめて置換ってのを稀によくやります。

そもそもSchemaVersionをいろんなところで出てくる設計よ…

 

やったー!エラーが消えたので無事ビルドすることができました!

 

次回

丁寧に書こうと思って書いてたら、既に3000字を余裕で越しているので、Warning 解消は次回にします。まぁ今からやるんですけど、記事分割しますね。

次回も作業自体は今回と同様のはず。

 

おわりに

disabled_rules に設定している force_cast を外してみると、あらびっくり。

54回も force_cast をしているみたい!大変!

これは後々、R.swift を入れて解消をしたいところもあるので、もうしばらくは disabled のままにしておきます。

force_try の方はもれなく全部Realm関連なので、そこを修正する時にどうにかします。

 

さて。次行ってみよう。

AppApp ,

Comments...

コメントは認証制です。詳しくは下記の注意をお読みください。お気軽にコメントお願いします!

Write a Comment

コメント時の注意

「Twitter」「Facebook」「Google+」「WordPress」のいずれかのアカウントをお持ちの方は各アカウントと連携することでコメントできます。 コメントしたことはSNSに流れませんので、アカウントをお持ちの方はこちらの方法でコメントを投稿して下さると嬉しいです。 アカウントをお持ちでない方はメールアドレスで投稿することができます。 初回コメント時は承認後に表示されます。

Related Memo...

UITableView.RowAnimation の .none はアニメーションするよ

UITableView.RowAnimation の .none はアニメーションがnoneなわけじゃなく、デフォルトの設定を使うよという意味らしい。

The inserted or deleted rows use the default animations.

なのでアニメーションしちゃう。今更の気づき。

 

iOS

UINavigationController + UIScrollView の組み合わせで使っている時に謎の余白ができる時

UINavigationController + UIScrollView の組み合わせで使っていて、UIScrollView 上に AutoLayout で上下左右0で View を設置しているのに、30px程度上にずれてしまうとき。

`navigationController.navigationBar.isTranslucent = false` にすると直るかもしれない。

ScrollView上のコンテンツとNavigationBarの重なっているところが透過していたら多分これで直せるはず。

通常のターゲットではちゃんと動いているのに、iOSSnapshotTestCase を用いたテストでだけこの対応が必要なのよくわからないけれど。。。

iOS

記事を書くほどでもないけれどメモっておきたいこと

テスト投稿。

例えばiphone7 の画面サイズ

750 × 1334
半分375 × 667

iOS
more