agentsclimarketplace

Swift patterns

Skill vibeeval/vibecosystem/skills/swift-patterns

SwiftUI view composition, @Observable patterns, async/await concurrency, TCA architecture, and Combine reactive streams.From its SKILL.md

Install
npx -y skills add vibeeval/vibecosystem --skill swift-patterns

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

SKILL.md

7.2 KB, ~1.5k tokens by cl100k_base, as published. Nobody here has run it

Swift Patterns

Modern Swift patterns for iOS/macOS application development.

SwiftUI View Composition

// Small, focused views composed together
struct ProductCard: View {
    let product: Product

    var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            ProductImage(url: product.imageURL)
            ProductInfo(name: product.name, price: product.price)
            RatingStars(rating: product.rating, count: product.reviewCount)
        }
        .padding()
        .background(.regularMaterial)
        .clipShape(RoundedRectangle(cornerRadius: 12))
    }
}

// Extract subviews for readability and reusability
struct ProductImage: View {
    let url: URL

    var body: some View {
        AsyncImage(url: url) { phase in
            switch phase {
            case .success(let image):
                image.resizable().aspectRatio(contentMode: .fill)
            case .failure:
                Image(systemName: "photo").foregroundStyle(.secondary)
            case .empty:
                ProgressView()
            @unknown default:
                EmptyView()
            }
        }
        .frame(height: 200)
        .clipped()
    }
}

// ViewModifier for reusable styling
struct CardModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding()
            .background(.regularMaterial)
            .clipShape(RoundedRectangle(cornerRadius: 12))
            .shadow(radius: 2)
    }
}

extension View {
    func cardStyle() -> some View {
        modifier(CardModifier())
    }
}

@Observable Pattern (iOS 17+)

import Observation

@Observable
final class ProductStore {
    var products: [Product] = []
    var isLoading = false
    var errorMessage: String?

    private let apiClient: APIClient

    init(apiClient: APIClient = .shared) {
        self.apiClient = apiClient
    }

    func loadProducts() async {
        isLoading = true
        errorMessage = nil

        do {
            products = try await apiClient.fetchProducts()
        } catch {
            errorMessage = error.localizedDescription
        }

        isLoading = false
    }

    func deleteProduct(_ product: Product) async throws {
        try await apiClient.deleteProduct(id: product.id)
        products.removeAll { $0.id == product.id }
    }
}

// Usage in SwiftUI (automatic tracking, no @Published needed)
struct ProductListView: View {
    @State private var store = ProductStore()

    var body: some View {
        List(store.products) { product in
            ProductCard(product: product)
        }
        .overlay {
            if store.isLoading { ProgressView() }
            if let error = store.errorMessage {
                ContentUnavailableView("Error", systemImage: "exclamationmark.triangle",
                                       description: Text(error))
            }
        }
        .task { await store.loadProducts() }
    }
}

Structured Concurrency

// TaskGroup for parallel async work
func loadDashboard() async throws -> Dashboard {
    async let profile = apiClient.fetchProfile()
    async let orders = apiClient.fetchRecentOrders()
    async let recommendations = apiClient.fetchRecommendations()

    // All three run concurrently, await all results
    return try await Dashboard(
        profile: profile,
        orders: orders,
        recommendations: recommendations
    )
}

// TaskGroup with dynamic number of tasks
func loadImages(urls: [URL]) async -> [URL: UIImage] {
    await withTaskGroup(of: (URL, UIImage?).self) { group in
        for url in urls {
            group.addTask {
                let image = try? await ImageLoader.load(url)
                return (url, image)
            }
        }

        var results: [URL: UIImage] = [:]
        for await (url, image) in group {
            if let image { results[url] = image }
        }
        return results
    }
}

// Actor for thread-safe shared state
actor ImageCache {
    private var cache: [URL: UIImage] = [:]
    private var inFlight: [URL: Task<UIImage, Error>] = [:]

    func image(for url: URL) async throws -> UIImage {
        if let cached = cache[url] { return cached }

        // Coalesce duplicate requests
        if let existing = inFlight[url] {
            return try await existing.value
        }

        let task = Task {
            let (data, _) = try await URLSession.shared.data(from: url)
            guard let image = UIImage(data: data) else {
                throw ImageError.invalidData
            }
            return image
        }

        inFlight[url] = task
        let image = try await task.value
        cache[url] = image
        inFlight[url] = nil
        return image
    }
}

TCA (The Composable Architecture) Pattern

import ComposableArchitecture

@Reducer
struct ProductFeature {
    @ObservableState
    struct State: Equatable {
        var products: [Product] = []
        var isLoading = false
        var alert: AlertState<Action>?
    }

    enum Action {
        case onAppear
        case productsLoaded(Result<[Product], Error>)
        case deleteProduct(Product)
        case alertDismissed
    }

    @Dependency(\.apiClient) var apiClient

    var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .onAppear:
                state.isLoading = true
                return .run { send in
                    let result = await Result { try await apiClient.fetchProducts() }
                    await send(.productsLoaded(result))
                }

            case .productsLoaded(.success(let products)):
                state.isLoading = false
                state.products = products
                return .none

            case .productsLoaded(.failure(let error)):
                state.isLoading = false
                state.alert = AlertState { TextState(error.localizedDescription) }
                return .none

            case .deleteProduct(let product):
                state.products.removeAll { $0.id == product.id }
                return .run { _ in try await apiClient.deleteProduct(id: product.id) }

            case .alertDismissed:
                state.alert = nil
                return .none
            }
        }
    }
}

Checklist

  • Views under 50 lines; extract subviews for composition
  • Use @Observable (iOS 17+) over ObservableObject/@Published
  • Structured concurrency with async let for parallel work
  • Actors for shared mutable state (not locks/queues)
  • ViewModifiers for reusable styling patterns
  • Environment for dependency injection in SwiftUI
  • Task cancellation handled (check Task.isCancelled)
  • Preview providers for every view with mock data

Anti-Patterns

  • Massive views: 200+ line body property (extract subviews)
  • @StateObject in child views: use @State or pass as parameter
  • Blocking main thread with synchronous work in views
  • Force unwrapping optionals: use guard let or nil coalescing
  • Ignoring task cancellation: leaked work after view disappears
  • Using singletons instead of dependency injection (untestable)

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.