Skip to content
Back to skills

Swiftui Patterns

ASecurity

SwiftUI UI patterns, state management, navigation, animations, and performance optimization.

  • 65 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added February 7, 2026
developmentgoswiftangularspringapiperformance

Works with

  • cli
  • api

Security analysis

A100/100

Scanned February 12, 2026

npx -y skills add ahmed3elshaer/everything-claude-code-mobile --skill swiftui-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Swiftui Patterns?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Swiftui Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/ahmed3elshaer-swiftui-patterns/badge)](https://www.skillsdirectory.com/skills/ahmed3elshaer-swiftui-patterns)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: swiftui-patterns
description: SwiftUI UI patterns, state management, navigation, animations, and performance optimization.
---

# SwiftUI Patterns

Modern SwiftUI patterns for iOS 17+ development.

## View Composition

### Small, Focused Views

```swift
// ✅ Good: Single responsibility
struct AvatarView: View {
    let imageURL: URL?
    let size: CGFloat

    var body: some View {
        AsyncImage(url: imageURL) { image in
            image.resizable()
        } placeholder: {
            Color.gray.opacity(0.2)
        }
        .frame(width: size, height: size)
        .clipShape(Circle())
    }
}

struct UserRow: View {
    let user: User

    var body: some View {
        HStack {
            AvatarView(imageURL: user.avatarURL, size: 48)
            VStack(alignment: .leading) {
                Text(user.name).font(.headline)
                Text(user.email).font(.caption).foregroundStyle(.secondary)
            }
        }
    }
}
```

## State Management

### @Observable (iOS 17+)

```swift
@Observable
class HomeViewModel {
    var items: [Item] = []
    var isLoading = false

    func loadItems() async {
        isLoading = true
        items = await api.fetchItems()
        isLoading = false
    }
}

struct HomeView: View {
    @State private var viewModel = HomeViewModel()

    var body: some View {
        List {
            if viewModel.isLoading {
                ProgressView()
            } else {
                ForEach(viewModel.items) { item in
                    Text(item.title)
                }
            }
        }
        .task {
            await viewModel.loadItems()
        }
    }
}
```

## Performance Patterns

### Lazy Containers

```swift
// ✅ LazyVStack for long lists
ScrollView {
    LazyVStack(spacing: 16) {
        ForEach(items) { item in
            ItemCard(item: item)
        }
    }
}

// ✅ LazyHStack for horizontal lists
ScrollView(.horizontal) {
    LazyHStack(spacing: 12) {
        ForEach(users) { user in
            UserAvatar(user: user)
        }
    }
}
```

### Equatable Views

```swift
struct ItemRow: View, Equatable {
    let item: Item

    static func == (lhs: Self, rhs: Self) -> Bool {
        lhs.item.id == rhs.item.id
    }

    var body: some View {
        HStack {
            Text(item.title)
            Text(item.price)
        }
    }
}
```

## Navigation

### NavigationStack

```swift
enum Route: Hashable {
    case home
    case detail(String)
    case profile(userId: String)
}

struct AppNavigation: View {
    @State private var path: [Route] = []

    var body: some View {
        NavigationStack(path: $path) {
            HomeView()
                .navigationDestination(for: Route.self) { route in
                    switch route {
                    case .home:
                        HomeView()
                    case .detail(let id):
                        DetailView(id: id)
                    case .profile(let userId):
                        ProfileView(userId: userId)
                    }
                }
        }
    }
}
```

### Sheet Presentation

```swift
struct RootView: View {
    @State private var presentedItem: Item?
    @State private var showingSettings = false

    var body: some View {
        List(items) { item in
            Button(item.title) { presentedItem = item }
        }
        .sheet(item: $presentedItem) { item in
            DetailSheet(item: item)
        }
        .sheet(isPresented: $showingSettings) {
            SettingsView()
        }
    }
}
```

## Gestures

### Custom Gestures

```swift
struct SwipeToDismiss: ViewModifier {
    @State private var offset: CGFloat = 0

    func body(content: Content) -> some View {
        content
            .offset(x: offset)
            .gesture(
                DragGesture()
                    .onChanged { value in
                        if value.translation.width < 0 {
                            offset = value.translation.width
                        }
                    }
                    .onEnded { value in
                        if value.translation.width < -100 {
                            // Dismiss action
                        }
                        offset = 0
                    }
            )
    }
}
```

## Animations

### Spring Animations

```swift
struct AnimatedButton: View {
    @State private var isPressed = false

    var body: some View {
        Circle()
            .fill(isPressed ? Color.blue : Color.gray)
            .frame(width: 80, height: 80)
            .scaleEffect(isPressed ? 0.9 : 1.0)
            .animation(.spring(response: 0.3, dampingFraction: 0.6), value: isPressed)
            .onTapGesture {
                withAnimation {
                    isPressed.toggle()
                }
            }
    }
}
```

### Phase Animations

```swift
struct StaggerAnimation: View {
    let items: [String]

    var body: some View {
        VStack {
            ForEach(Array(items.enumerated()), id: \.offset) { index, item in
                Text(item)
                    .transition(.scale.combined(with: .opacity))
            }
        }
    }
}

// Usage with stagger
.transition(.asymmetric(
    insertion: .scale.combined(with: .opacity),
    removal: .opacity
))
```

## Custom Modifiers

```swift
struct CardModifier: ViewModifier {
    var backgroundColor: Color = .white
    var cornerRadius: CGFloat = 12
    var shadowRadius: CGFloat = 4

    func body(content: Content) -> some View {
        content
            .padding()
            .background(backgroundColor)
            .clipShape(RoundedRectangle(cornerRadius: cornerRadius))
            .shadow(radius: shadowRadius)
    }
}

extension View {
    func cardStyle(
        backgroundColor: Color = .white,
        cornerRadius: CGFloat = 12,
        shadowRadius: CGFloat = 4
    ) -> some View {
        modifier(CardModifier(
            backgroundColor: backgroundColor,
            cornerRadius: cornerRadius,
            shadowRadius: shadowRadius
        ))
    }
}
```

## Shapes & Styles

### Custom Shapes

```swift
struct BlobShape: Shape {
    var cornerRadius: CGFloat = 40
    var animatableData: CGFloat = cornerRadius

    func path(in rect: CGRect) -> Path {
        var path = Path()
        let points = [
            CGPoint(x: 0, y: 0),
            CGPoint(x: rect.width, y: 0),
            CGPoint(x: rect.width, y: rect.height),
            CGPoint(x: 0, y: rect.height)
        ]
        // Create blob shape
        return path
    }
}

// Usage
BlobShape(cornerRadius: 50)
    .fill(Color.blue.gradient)
```

### Gradients

```swift
Circle()
    .fill(
        LinearGradient(
            colors: [.blue, .purple],
            startPoint: .topLeading,
            endPoint: .bottomTrailing
        )
    )

// Angular gradient
Circle()
    .fill(AngularGradient(
        colors: [.red, .yellow, .green, .blue, .red],
        center: .center
    ))
```

## Grid Layouts

```swift
LazyVGrid(
    columns: [
        GridItem(.adaptive(minimum: 100), spacing: 16)
    ],
    spacing: 16
) {
    ForEach(items) { item in
        ItemCell(item: item)
    }
}
```

---

**Remember**: SwiftUI views are values. Compose them, transform them, and let the framework handle rendering.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…