swift-best-practices について
swift-best-practicesは、iOSやmacOS向けのSwiftコードを作成、レビュー、移行する開発者向けのガイダンススキルです。Swift 6の並行処理安全性、API設計、コード品質を扱います。
主な機能
- 01Swift 6の並行処理と隔離の指針
- 02async/awaitとキャンセルの実践
- 03APIの命名と引数ラベルの規則
- 04利用可能性の注釈と移行の指針
- 05詳細なトピックのリファレンス
活用シーン
- 01iOSまたはmacOS向けSwiftコードの作成
- 02並行処理の安全性とActor隔離のレビュー
- 03Swift 5からSwift 6へのプロジェクト移行
- 04Sendableや隔離に関する問題の解決
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ sammcj/ agentic-coding --skill swift-best-practicesインストール後、Claude Code で/swift-best-practicesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/api-design.mdavailability-patterns.mdconcurrency.mdswift6-features.md詳細
Swift のベストプラクティススキル
概要
macOS 15.7 以降を対象とする iOS および macOS プロジェクト向けに、Swift 6 以降の機能、並行処理の安全性、API 設計の原則、コード品質のガイドラインに焦点を当てた、最新の Swift 開発のベストプラクティスを適用します。
このスキルを使用する場面
次のような場合に、このスキルを使用してください。
- iOS または macOS アプリケーション向けに新しい Swift コードを書く場合
- 正確性、安全性、スタイルの観点から Swift コードをレビューする場合
- Swift の並行処理機能(async/await、actors、MainActor)を実装する場合
- Swift API とパブリックインターフェースを設計する場合
- コードを Swift 5 から Swift 6 に移行する場合
- Sendable/分離に関連する並行処理の警告、データ競合の問題、コンパイラーエラーに対処する場合
- Swift 6 および 6.2 で導入された最新の Swift 言語機能を使用する場合
基本ガイドライン
基本原則
- 使用箇所での明確さが最も重要です。宣言だけでなく、ユースケースを調べて設計を評価してください
- 簡潔さより明確さを重視します。コードの簡潔さは最小限の文字数ではなく、型システムによって実現されます
- すべてのパブリック宣言にドキュメントを記述してください。機能を簡潔に説明できない場合、API の設計に問題がある可能性があります
- 型ではなく役割に基づいて命名してください。
var string = "Hello"ではなく、var greeting = "Hello"とします - シンプルさによって洗練を目指し、複雑さが本当に必要な場合を除いて、過剰な設計を避けてください
Swift 6 の並行処理モデル
Swift 6 では、領域ベースの分離(SE-0414)による完全な並行処理チェックがデフォルトで有効になります。コンパイラーはコードの安全性を証明することで、多くの誤検知を排除しながら、実際の並行処理の問題をコンパイル時に検出します。
重要なポイント:
- 非同期 ≠ バックグラウンド — 非同期関数は中断できますが、自動的にバックグラウンドスレッドで実行されるわけではありません
- アクターは、自動同期によって変更可能な共有状態を保護します
@MainActorにより、UI 関連コードがメインスレッドで実行されます- グローバルアクターで分離された型は、自動的に
Sendableになります
必須パターン
Async/Await
// Parallel execution with async let
func fetchData() async -> (String, Int) {
async let stringData = fetchString()
async let intData = fetchInt()
return await (stringData, intData)
}
// Always check cancellation in long-running operations
func process(_ items: [Item]) async throws -> [Result] {
var results: [Result] = []
for item in items {
try Task.checkCancellation()
results.append(await process(item))
}
return results
}
UI コードでの MainActor
// Apply at type level for consistent isolation
@MainActor
class ContentViewModel: ObservableObject {
@Published var images: [UIImage] = []
func fetchData() async throws {
self.images = try await fetchImages()
}
}
// Avoid MainActor.run when direct await works
await doMainActorStuff() // Good
await MainActor.run { doMainActorStuff() } // Unnecessary
アクター分離
actor DataCache {
private var cache: [String: Data] = [:]
func store(_ data: Data, forKey key: String) {
cache[key] = data // No await needed inside actor
}
nonisolated func cacheType() -> String {
return "DataCache" // No await needed - doesn't access isolated state
}
}
避けるべきよくある落とし穴
- 関数に不必要な
asyncを付けないでください — 非同期呼び出し規約にはオーバーヘッドがあります - async/await で
DispatchSemaphoreを使用しないでください — デッドロックが発生するおそれがあります - 状態を持たないアクターを作成しないでください — 代わりに非分離の非同期関数を使用してください
- 分離の分割を避けてください — 1 つの型の中で複数の分離ドメインを混在させないでください
- タスクのキャンセルを確認してください — 時間のかかる処理では
Task.checkCancellation()を確認する必要があります - 非同期はバックグラウンドを意味すると考えないでください — 必要に応じて、処理を明示的にバックグラウンドへ移してください
- 過度なコンテキスト切り替えを避けてください — 同じ分離ドメイン内で処理をまとめてください
API 設計のクイックリファレンス
命名規則
- 型/プロトコル:
UpperCamelCase - その他すべて:
lowerCamelCase - 能力を表すプロトコル:
-able、-ible、-ingの接尾辞(Equatable、ProgressReporting) - ファクトリーメソッド:
makeで始めます(x.makeIterator()) - 変更を伴うペア:命令形と過去分詞形(
x.sort()/x.sorted())
副作用に応じたメソッドの命名
- 副作用なし:名詞句(
x.distance(to: y)) - 副作用あり:命令形の動詞(
x.append(y)、x.sort())
引数ラベル
- 引数を区別できない場合は省略します:
min(number1, number2) - 値を保持する変換では、最初のラベルを省略します:
Int64(someUInt32) - 前置詞句では、前置詞の位置にラベルを付けます:
x.removeBoxes(havingLength: 12) - その他の引数にはすべてラベルを付けます
Swift 6 の破壊的変更
型に @MainActor を明示的に付ける必要があります(SE-0401)
プロパティラッパーによって、アクター分離が自動的に推論されることはなくなりました。
@MainActor
struct LogInView: View {
@StateObject private var model = ViewModel()
}
グローバル変数は並行処理に対して安全である必要があります(SE-0412)
static let config = Config() // Constant - OK
@MainActor static var state = State() // Actor-isolated - OK
nonisolated(unsafe) var cache = [String: Data]() // Unsafe - use with caution
その他の変更
@UIApplicationMain/@NSApplicationMainは非推奨です(@mainを使用してください)- 存在型には
anyが必要です - インポートの可視性には、明示的なアクセス制御が必要です
API の利用可能性パターン
// Basic availability
@available(macOS 15, iOS 18, *)
func modernAPI() { }
// Deprecation with message
@available(*, deprecated, message: "Use newMethod() instead")
func oldMethod() { }
// Renaming with auto-fix
@available(*, unavailable, renamed: "newMethod")
func oldMethod() { }
// Runtime checking
if #available(iOS 18, *) {
// iOS 18+ code
}
// Inverted checking (Swift 5.6+)
if #unavailable(iOS 18, *) {
// iOS 17 and lower
}
主な違い:
deprecated- 警告を表示しますが、使用できますobsoleted- 指定されたバージョンからエラーになりますunavailable- エラーとなり、使用を完全に禁止します
このスキルの使い方
コードを書くとき
- 役割に基づき、明瞭さを優先する原則に従って命名規則を適用します
- 適切な分離を使用します(UI には
@MainActor、可変状態にはアクターを使用します) - 適切なキャンセル処理を含め、async/await パターンを正しく実装します
- Swift 6 の並行処理モデルに従い、コンパイラのフロー解析を信頼します
- 公開 API に、明確で簡潔な要約を記述します
コードをレビューするとき
- 並行処理の安全性に関する違反がないか確認します
- アクター分離と Sendable への準拠が適切か確認します
- 非同期関数がキャンセルを適切に処理しているか確認します
- API の命名が Swift のガイドラインに従っているか検証します
- 対象プラットフォームに対して、利用可能性のアノテーションが正しいか確認します
コード品質基準
- コメントは最小限にします。可能な限り、コード自体が説明的であるべきです
- 過剰な設計や不要な抽象化は避けます
- 型ではなく役割に基づいた、意味のある変数名を使用します
- 確立されたプロジェクトのアーキテクチャとパターンに従います
filter().countよりcount(where:)を優先します- サイズが固定され、パフォーマンスが重要なデータには
InlineArrayを使用します - コンパイラの並行処理フロー解析を信頼し、不要な
Sendable準拠は避けます
リソース
references/
詳細な情報が必要な場合に読み込む、詳細なリファレンス資料です。
- api-design.md - API 設計規約、ドキュメントの基準、パラメーターのガイドライン、命名パターンの全般
- concurrency.md - async/await パターン、アクターのベストプラクティス、よくある落とし穴、パフォーマンスに関する考慮事項、スレッドセーフのパターンの詳細
- swift6-features.md - Swift 6/6.2 の新しい言語機能、破壊的変更、移行戦略、最新のパターン
- availability-patterns.md -
@available属性の包括的な使用方法、非推奨化の戦略、プラットフォームのバージョン管理
上記の基本ガイドラインを超える詳細な情報が必要な場合は、これらのリファレンスを読み込みます。
プラットフォーム要件
- Swift 6 の機能には、Swift 6.0 以降のコンパイラが必要です
- InlineArray と強化された並行処理機能には、Swift 6.2 以降が必要です
- 適切な SDK を備えた macOS 15.7 以降
- 最新のプラットフォーム機能には iOS 18 以降が必要です
- 実行時のプラットフォーム検出には
#availableを使用します - API の利用可能性の指定には
@availableを使用します
コメント
Markdown 対応