
SwiftUI Patterns
FreeImplement modern SwiftUI architecture for iOS/macOS apps.
Free · Opens the source repo
What SwiftUI Patterns does
SwiftUI Patterns provides a comprehensive guide to building modern user interfaces on Apple platforms using SwiftUI. This skill focuses on best practices for state management, view composition, navigation, and performance optimization, essential for creating high-performance, declarative UIs. By utilizing the Observation framework and type-safe navigation techniques, developers can streamline their workflow and enhance the user experience in their applications.
The skill covers various state management strategies, including the use of property wrappers like @State, @Binding, and @Observable. It emphasizes the importance of selecting the appropriate wrapper for different scenarios, ensuring efficient data flow and reactivity within the app. Additionally, the skill provides detailed examples of how to implement view models effectively, allowing for better separation of concerns and easier maintenance.
For navigation, SwiftUI Patterns introduces NavigationStack and NavigationPath, enabling developers to create type-safe routing within their applications. This approach not only improves code clarity but also reduces the likelihood of runtime errors. Performance optimization techniques are also discussed, such as using lazy containers for large collections and ensuring stable identifiers for list items, which are crucial for maintaining smooth scrolling and rendering.
Overall, SwiftUI Patterns is designed for developers and designers looking to adopt best practices in SwiftUI development. Whether you're building a new app or enhancing an existing one, this skill will help you implement efficient and modern UI patterns that align with Apple's design principles.
When to use it
Use this skill when building SwiftUI applications that require effective state management, navigation, and performance optimization.
When not to use it
This skill may not be suitable for projects that do not utilize SwiftUI or require non-declarative UI frameworks.
What you can build with it
Building a New SwiftUI App
Utilize SwiftUI Patterns to establish a solid architectural foundation for your new iOS or macOS application.
Optimizing an Existing Application
Apply the performance optimization techniques from this skill to enhance the responsiveness of your current SwiftUI app.
Implementing Type-Safe Navigation
Use the navigation patterns outlined in this skill to create a more robust routing system in your SwiftUI project.
How to install SwiftUI Patterns
View source1. Install with the skills CLI
npx skills add affaan-m/ecc/swiftui-patterns --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by affaan-mSwiftUI パターン
Appleプラットフォーム向けのモダンなSwiftUIパターン。宣言的で高性能なユーザーインターフェースを構築するために使用する。Observationフレームワーク、ビュー合成、型安全なナビゲーション、パフォーマンス最適化をカバーする。
起動条件
- SwiftUIビューを構築し、状態を管理する場合(
@State、@Observable、@Binding) NavigationStackを使用したナビゲーションフローを設計する場合- ビューモデルとデータフローを構築する場合
- リストと複雑なレイアウトのレンダリングパフォーマンスを最適化する場合
- SwiftUIで環境値と依存性注入を使用する場合
状態管理
プロパティラッパーの選択
最も適したシンプルなラッパーを選択する:
| ラッパー | 使用場面 |
|---|---|
@State | ビューローカルな値型(トグル、フォームフィールド、シート表示) |
@Binding | 親ビューの @State への双方向参照 |
@Observable クラス + @State | 複数のプロパティを持つ所有モデル |
@Observable クラス(ラッパーなし) | 親ビューから渡される読み取り専用参照 |
@Bindable | @Observable プロパティへの双方向バインディング |
@Environment | .environment() で注入された共有依存関係 |
@Observable ViewModel
ObservableObject ではなく @Observable を使用する——プロパティレベルの変更を追跡するため、SwiftUIは変更されたプロパティを読み取ったビューのみを再レンダリングする:
@Observable
final class ItemListViewModel {
private(set) var items: [Item] = []
private(set) var isLoading = false
var searchText = ""
private let repository: any ItemRepository
init(repository: any ItemRepository = DefaultItemRepository()) {
self.repository = repository
}
func load() async {
isLoading = true
defer { isLoading = false }
items = (try? await repository.fetchAll()) ?? []
}
}
ViewModelを使用するビュー
struct ItemListView: View {
@State private var viewModel: ItemListViewModel
init(viewModel: ItemListViewModel = ItemListViewModel()) {
_viewModel = State(initialValue: viewModel)
}
var body: some View {
List(viewModel.items) { item in
ItemRow(item: item)
}
.searchable(text: $viewModel.searchText)
.overlay { if viewModel.isLoading { ProgressView() } }
.task { await viewModel.load() }
}
}
環境への注入
@EnvironmentObject の代わりに @Environment を使用する:
// Inject
ContentView()
.environment(authManager)
// Consume
struct ProfileView: View {
@Environment(AuthManager.self) private var auth
var body: some View {
Text(auth.currentUser?.name ?? "Guest")
}
}
ビュー合成
無効化を制限するためにサブビューを抽出する
ビューを小さく焦点を絞った構造体に分割する。状態が変化した場合、その状態を読み取ったサブビューのみが再レンダリングされる:
struct OrderView: View {
@State private var viewModel = OrderViewModel()
var body: some View {
VStack {
OrderHeader(title: viewModel.title)
OrderItemList(items: viewModel.items)
OrderTotal(total: viewModel.total)
}
}
}
再利用可能なスタイルのための ViewModifier
struct CardModifier: ViewModifier {
func body(content: Content) -> some View {
content
.padding()
.background(.regularMaterial)
.clipShape(RoundedRectangle(cornerRadius: 12))
}
}
extension View {
func cardStyle() -> some View {
modifier(CardModifier())
}
}
ナビゲーション
型安全な NavigationStack
NavigationStack と NavigationPath を使用して、プログラム的で型安全なルーティングを実現する:
@Observable
final class Router {
var path = NavigationPath()
func navigate(to destination: Destination) {
path.append(destination)
}
func popToRoot() {
path = NavigationPath()
}
}
enum Destination: Hashable {
case detail(Item.ID)
case settings
case profile(User.ID)
}
struct RootView: View {
@State private var router = Router()
var body: some View {
NavigationStack(path: $router.path) {
HomeView()
.navigationDestination(for: Destination.self) { dest in
switch dest {
case .detail(let id): ItemDetailView(itemID: id)
case .settings: SettingsView()
case .profile(let id): ProfileView(userID: id)
}
}
}
.environment(router)
}
}
パフォーマンス
大規模なコレクションにレイジーコンテナを使用する
LazyVStack と LazyHStack はビューが表示される時のみ作成する:
ScrollView {
LazyVStack(spacing: 8) {
ForEach(items) { item in
ItemRow(item: item)
}
}
}
安定した識別子
ForEach では常に安定した一意のIDを使用する——配列インデックスは避ける:
// Use Identifiable conformance or explicit id
ForEach(items, id: \.stableID) { item in
ItemRow(item: item)
}
body 内での高コストな操作を避ける
body内でI/O、ネットワーク呼び出し、重い計算を絶対に実行しない- 非同期処理には
.task {}を使用する——ビューが消えると自動的にキャンセルされる - スクロールビューでは
.sensoryFeedback()と.geometryGroup()を慎重に使用する - リストでは
.shadow()、.blur()、.mask()の使用を最小化する——画面外レンダリングを引き起こす
Equatable に準拠する
bodyの計算が高コストなビューには、不要な再レンダリングをスキップするために Equatable に準拠する:
struct ExpensiveChartView: View, Equatable {
let dataPoints: [DataPoint] // DataPoint must conform to Equatable
static func == (lhs: Self, rhs: Self) -> Bool {
lhs.dataPoints == rhs.dataPoints
}
var body: some View {
// Complex chart rendering
}
}
プレビュー
インラインのモックデータで #Preview マクロを使用して素早い反復を行う:
#Preview("Empty state") {
ItemListView(viewModel: ItemListViewModel(repository: EmptyMockRepository()))
}
#Preview("Loaded") {
ItemListView(viewModel: ItemListViewModel(repository: PopulatedMockRepository()))
}
避けるべきアンチパターン
- 新しいコードで
ObservableObject/@Published/@StateObject/@EnvironmentObjectを使用する——@Observableに移行する bodyやinit内に直接非同期処理を置く——.task {}または明示的なロードメソッドを使用する- データを所有しないサブビューでViewModelを
@Stateとして作成する——代わりに親ビューから渡す AnyViewによる型消去を使用する——条件付きビューには@ViewBuilderまたはGroupを優先する- ActorとのデータのやりとりにおいてSendable要件を無視する
参照
Actorベースの永続化パターンについては、スキル swift-actor-persistence を参照。
プロトコルベースのDIとSwift Testingを使用したテストについては、スキル swift-protocol-di-testing を参照。
Frequently asked questions about SwiftUI Patterns
Similar skills
Playwright Component Testing
Test React and Vue components in isolation with Playwright.
Fluent UI Blazor
Integrate Fluent UI components in Blazor applications effortlessly.
Build MCP App
Create interactive UI widgets for MCP servers.
Web Design Reviewer
Identify and fix design issues in websites efficiently.
Markstream Install
Seamlessly integrate Markstream for Markdown rendering.
GSAP & Framer Scroll Animation
Create advanced scroll animations effortlessly.
