最近イケてると思ったiOSアプリ開発のパターン

UIApplication.shared.delegate as! AppDelegate やめる

static var shared: AppDelegate? {
    return UIApplication.shared.delegate as? AppDelegate
}

コードでAutoLayoutの制約をつける簡易メソッド

func bindFrameToSelf(subview: UIView) {
    // この中で縦横のAutoLayout制約を宣言
}

bindFrameToSelf(subview: hogeView)

アプリで表示する文字列を列挙子にまとめる

struct Strings {
    enum Home: String {
        case title = "ホーム"
        case welcome = "ようこそ"
    }
}

ってやって、ViewControllerで

self.title = Strings.Home.title.rawValue
welcomeLabel.text = Strings.Home.welcome.rawValue

とかやると文字列を気にしなくて良いので気持ちが楽

このそれぞれにさらにStringLocalizableみたいなプロトコルに対応させるようにすれば言語対応ができる

アラートを表示するメソッドをAppDelegateに書く

いままで

let ac = UIAlertController(title: "アラート", message: "アラートです", preferredStyle: .alert)
ac.addAction(.......省略......)
self.present(ac, animated: true)

みたいなやつを色んなところに書いてしまってた。これをやるメソッドをAppDelegateに書いてしまうと気持ちが楽。

func showAlert(withTitle 
    title: String = "アラートタイトルの初期値",
    message: String = "アラート内容の初期値",
    buttonTitle: String = "ボタンタイトルの初期値",
    handler: (() -> ())? = nil) {
    
    DispatchQueue.main.async {
        // ① 一番前のViewControllerなりWindowを得る
        // ② アラートや自前UIViewを作る
        // ③ VCやWindowにaddSubviewしたりpresentしたりする
    }
}

読み込みウィンドウをAppDelegateで保持しておく

private var progressWindow: HogeProgressWindow?

private func setupProgressWindow() {
    // prepare view
}

このウィンドウを、APIClientのコネクション数に応じて表示/非表示させれば良さそう

RealmのマイグレーションIDを日付にする

Realmのスキーマバージョンを日付にすると管理が楽になる?(かも?)

APIClientの結果を必ずRealmにぶち込む

ローカルにぶっこんどいておくと便利なエンティティとかはやっておく

APIClientが通信しているとき必ずprogressを回す

Alamofireとかがデータリクエストをするところの最初でインジケータを回してしまえばいい。VCとかで考える必要がなくなる
post, put, deleteリクエストのときは画面暗くして一時的に操作不能にするとかそういうのもここで突っ込んでしまうと気持ちが楽

viewにまつわる操作をしたかったらAppDelegateにapiCountみたいな変数を生やしておいて、APIClientからそこをインクリメントしたりデクリメントするメソッドにアクセスして(apiCount自体はprivateで宣言しておいた方が良い気がする)、AppDelegate側でそれを監視してビューの出し分けをすれば良い

アセットファイルを画面ごとに分ける

.xcassetsファイルは何個も作れるらしい
親でResourceフォルダみたいなのを作って、そこに画面.xcassetsとかで作ってあげるとよさそう

リリースビルドでは出ないprintメソッド

class Debug {
    class func print(_ items: Any..., separator: String = " ", terminator: String = "\n", function: String = #function) {
   #if DEBUG
        Swift.print(Args(args: items, separator: separator), separator: ......)
   #endif
    }
}

あとはそもそも Swift.debugPrint とか Swift.dump とかあるみたいなのでそれも適宜調べてみて