Const構造体
class ViewController: UIViewController {
func action() {
let defaultKey = "ThisIsKey"
ValueStore.get(defaultKey)
}
}
メソッドの中にキーや数値情報を書くと、他のクラス利用者が止む無く変更したい場合にメソッドに手を加える必要が出たりそもそもの変数の場所を探す必要が出て来る。
class ViewController: UIViewController {
private struct Const {
static let defaultKey = "ThisIsKey"
}
func action() {
ValueStore.get(Const.defaultKey)
}
}
このようにConst構造体にまとめることで、定数を一箇所に集約させることが出来る。
+Extensions.swift
Extensionを生やす場合、クラス名+Extensions.swiftという名前にしてExtensionsグループに入れている。
setupメソッド
主にsetupAppearance
とsetupSubscriber
というメソッドをほぼ必ず作るようにしている。
これはviewDidLoad等のメソッドの中でUI装飾メソッドとRx/Gesture/delegate等のコールバックのセットアップ等が混在する事が要因で、このようにsetupメソッドとして分割することで修正箇所が明確になる
DataSourceクラスを作る
ViewControllerに書きがちなUITableViewDelegateはDataSourceクラスに分けている。
理由はViewControllerが肥大化するから。
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
lazy var dataSource: ViewControllerDataSource = .init(with: self.tableView)
override func viewDidLoad() {
super.viewDidLoad()
}
}
class ViewControllerDataSource: NSObject, UITableViewDelegate, UITableViewDataSource {
convenience init(with tableView: UITableView) {
tableView.delegate = self
tableView.dataSource = self
}
}
こんな感じ。
実際はViewModelクラスと一緒に作ってreloadDataのタイミング等を管理している。
didSetを使わない
hoge.uppperPadding = 40.0
というメソッドを呼んで、実際は
var upperPadding: CGFloat = 0.0 {
didSet {
//めっちゃ重い処理
}
}
だったら怖いから。
プロパティへの代入は代入に留めたい。
プロパティ:軽い処理
メソッド:重めの処理
という印象があると思うので、それには逆らわないようにする。
`self` = selfを使わない
closureでselfを使う際に
action = { [weak self] in
guard let `self` = self else { return }
self.update()
}
みたいな感じでself?を潰す手法があるんだけど、これは
・ そもそもguard let
self = self else { return }
を忘れた時に気がつけなくなる
・ selfと性質が厳密には違うのに同じ名前を使いたくない
という理由です。
@IBOutlet
にprivateを付ける
外から見た時にアクセス出来る必要が無いのに補完に出たりするのでprivateにしておく。
またIBOutletは厳密にはnilである可能性があるので、そういったタイミングでアクセスさせないという意図もある。
タップイベント等を流す時はちゃんとPublishSubjectを生やしてviewDidLoadとかでbindする
Optionalの定義には = nil
を書く
class Button: UIView {
var color: UIColor?
}
となっていると、イニシャライザで初期化すべきなのか混乱するから。
Button(color: color)
みたいなのがあるのかと思ってしまう。(structでもそういう動作だし)
class Button: UIView {
var color: UIColor? = nil
}
こうなっていると、とりあえずcolorに関しては気にしなくていいと分かるし、初期値が明確になる。
TODOにワーニングを付ける
ObjC時代はTODOはワーニングだったが、Swiftからはワーニングにならなくなった。
RunScriptに
if [ "${CONFIGURATION}" = "Debug" ]; then
TAGS="TODO:"
echo "searching ${SRCROOT} for ${TAGS}"
find "${SRCROOT}" \( -name "*.swift" \) -print0 | xargs -0 egrep --with-filename --line-number --only-matching "($TAGS).*\$" | perl -p -e "s/($TAGS)/ warning: \$1/"
fi
を追加してワーニングにするようにしている。
R.swiftの色情報をHexで管理する
カラーリテラルやR.SwiftデフォルトのClrではカラーコードが分からないので、txtにHexを書いてClrに変換している。
https://github.com/noppefoxwolf/HexToClr
分かりにくい処理はPlaygroundファイルを同梱する
Variableって最初ストリーム流れるんだっけ…?
みたいな疑問が出たらすぐPlaygroundで確かめてXcodeWorkspaceにいれて残しておく。
冗長な処理はServiceやFactoryに隠す
どうしてもFoundationのメソッドで冗長な書き方をしないといけない場合がある(VisionAPIとか…)ので、そういうのはServiceとかに隠す。
(クリーンコード警察みたいでヤダナコレ…)
なんか思いついたら追記します