| name | swift-coder |
| description | A skill for applying the defined coding rules to Swift coding. Always activate this skill and apply the rules when writing Swift code or when asked to modify .swift files. |
Swift Coding Rules
このスキルは、Swiftコードの一貫性を保つための特定のコーディングルールを適用します。
📝 コードスタイル
self. の省略
func updateLabel() {
titleLabel.text = title
}
func updateLabel() {
self.titleLabel.text = self.title
}
fetch { [weak self] result in
guard let self else { return }
titleLabel.text = result.title
}
init(title: String) {
self.title = title
}
return の省略
func getTitle() -> String {
"Hello, Swift"
}
func getTitle() -> String {
return "Hello, Swift"
}
let mapped = names.map { $0.uppercased() }
let message = switch status {
case .active: "Active"
case .inactive: "Inactive"
}
三項演算子の括弧
let message = isSuccess ? "OK" : "NG"
let color = (count > 0) ? .green : .red
KeyPathアクセスを好む
let titles = items.map(\.title)
let activeItems = items.filter(\.isActive)
let validItems = items.compactMap(\.self)
let titles = items.map { $0.title }
let activeItems = items.filter { $0.isActive }
let validItems = items.compactMap { $0 }
reduce(initValue, +)を好む
let sum = numbers.reduce(0, +)
let product = numbers.reduce(1, *)
let sum = numbers.reduce(0) { $0 + $1 }
let product = numbers.reduce(1) { $0 * $1 }
インナータイプは extension に切り出す
class User {
let id: Int
}
extension User {
struct Configuration {
let isAdmin: Bool
}
}
class User {
let id: Int
struct Configuration {
let isAdmin: Bool
}
}
🖼️ SwiftUI
Stack内の要素間に空行を入れる
VStack {
HeaderView()
ContentView()
}
VStack {
HeaderView()
ContentView()
}
🏛️ 状態管理
ステートを持つ場所を限定する
アーキテクチャ上許可された場所(ReduxのState、MVVMのViewModel)でのみ状態を持つ。それ以外のアクター(Service、Repository など)はステートレスを保つ。どうしても必要な場合はユーザーに承認を得る。
状態の分散はSSOT原則を破り、バグの温床となるため。
📐 型設計
排他的な状態はenumで表現する
相互排他的なフィールド群 + フラグ → enum の associated value に統合し、不可能な状態を型レベルで排除する。
struct Order {
var fulfillment: Fullfillment
enum Fullfillment {
case delivery(address: String)
case pickup(storeID: String)
}
}
struct Order {
var deliveryAddress: String
var pickupStoreID: String
let isDelivery: Bool
}
モデルに責務を持たせる
自身のデータに関するロジック(バリデーション、値の算出、他の型からの変換 など)はモデル自身に実装する。
enum Fullfillment {
case delivery(address: String)
case pickup(storeID: String)
}
extension Fullfillment {
init(from source: OrderSource) {
if source.storeID.isEmpty {
self = .delivery(address: source.address)
} else {
self = .pickup(storeID: source.storeID)
}
}
var isValid: Bool {
switch self {
case .delivery(let address): !address.isEmpty
case .pickup(let storeID): !storeID.isEmpty
}
}
}
命名は意図を表現する
実装(何をチェックするか)ではなく、意図(なぜチェックするか)を名前にする。
var isValid: Bool
var isEmpty: Bool
重要文献