Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Expert skill for native iOS development with Swift and SwiftUI
.claude/skills/a5c-ai-swift-swiftui-development/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 60% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 71% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 190% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 347% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 131% | 0% |
This skill provides expert capabilities for native iOS development using Swift and SwiftUI. It enables generation of SwiftUI views, implementation of state management patterns, Combine reactive programming, and comprehensive Xcode build operations.
bash - Execute xcodebuild, swift, and xcrun commandsread - Analyze Swift source files and Xcode project configurationswrite - Generate and modify Swift code and SwiftUI viewsedit - Update existing Swift code and configurationsglob - Search for Swift files and Xcode project filesgrep - Search for patterns in Swift codebaseThis skill integrates with the following processes:
swiftui-app-development.js - SwiftUI app architectureios-core-data-implementation.js - Core Data integrationios-push-notifications.js - APNs configurationios-appstore-submission.js - App Store submissionmobile-accessibility-implementation.js - Accessibility featuresMyApp/
├── MyApp/
│ ├── App/
│ │ ├── MyAppApp.swift
│ │ └── ContentView.swift
│ ├── Features/
│ │ └── FeatureName/
│ │ ├── Views/
│ │ ├── ViewModels/
│ │ └── Models/
│ ├── Core/
│ │ ├── Extensions/
│ │ ├── Utilities/
│ │ └── Services/
│ ├── Resources/
│ │ └── Assets.xcassets
│ └── Info.plist
├── MyAppTests/
├── MyAppUITests/
└── MyApp.xcodeprojswift// MyAppApp.swift import SwiftUI @main struct MyAppApp: App { @StateObject private var appState = AppState() var body: some Scene { WindowGroup { ContentView() .environmentObject(appState) } } }
swift// Features/Home/Views/HomeView.swift import SwiftUI struct HomeView: View { @StateObject private var viewModel = HomeViewModel() @State private var searchText = "" var body: some View { NavigationStack { List { ForEach(viewModel.filteredItems) { item in NavigationLink(value: item) { ItemRowView(item: item) } } } .navigationTitle("Home") .searchable(text: $searchText) .onChange(of: searchText) { _, newValue in viewModel.search(query: newValue) } .navigationDestination(for: Item.self) { item in ItemDetailView(item: item) } .refreshable { await viewModel.refresh() } } } } #Preview { HomeView() }
swift// Features/Home/ViewModels/HomeViewModel.swift import Foundation import Combine @MainActor final class HomeViewModel: ObservableObject { @Published private(set) var items: [Item] = [] @Published private(set) var filteredItems: [Item] = [] @Published private(set) var isLoading = false @Published private(set) var error: Error? private let itemService: ItemServiceProtocol private var cancellables = Set<AnyCancellable>() init(itemService: ItemServiceProtocol = ItemService()) { self.itemService = itemService setupBindings() Task { await loadItems() } } private func setupBindings() { $items .assign(to: &$filteredItems) } func loadItems() async { isLoading = true error = nil do { items = try await itemService.fetchItems() } catch { self.error = error } isLoading = false } func search(query: String) { if query.isEmpty { filteredItems = items } else { filteredItems = items.filter { $0.title.localizedCaseInsensitiveContains(query) } } } func refresh() async { await loadItems() } }
swift// Core/ViewModifiers/CardStyle.swift import SwiftUI struct CardStyle: ViewModifier { var cornerRadius: CGFloat = 12 var shadowRadius: CGFloat = 4 func body(content: Content) -> some View { content .background(Color(.systemBackground)) .cornerRadius(cornerRadius) .shadow(color: .black.opacity(0.1), radius: shadowRadius, x: 0, y: 2) } } extension View { func cardStyle(cornerRadius: CGFloat = 12, shadowRadius: CGFloat = 4) -> some View { modifier(CardStyle(cornerRadius: cornerRadius, shadowRadius: shadowRadius)) } }
swift// App/Router.swift import SwiftUI enum Route: Hashable { case home case detail(id: String) case settings case profile(userId: String) } final class Router: ObservableObject { @Published var path = NavigationPath() func navigate(to route: Route) { path.append(route) } func navigateBack() { path.removeLast() } func navigateToRoot() { path.removeLast(path.count) } func handle(url: URL) -> Bool { guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true), let host = components.host else { return false } switch host { case "detail": if let id = components.queryItems?.first(where: { $0.name == "id" })?.value { navigate(to: .detail(id: id)) return true } case "profile": if let userId = components.queryItems?.first(where: { $0.name == "userId" })?.value { navigate(to: .profile(userId: userId)) return true } default: break } return false } }
bash# Build for simulator xcodebuild -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 15 Pro' build # Build for device xcodebuild -scheme MyApp -destination 'generic/platform=iOS' build # Archive for distribution xcodebuild -scheme MyApp -archivePath ./build/MyApp.xcarchive archive # Export IPA xcodebuild -exportArchive -archivePath ./build/MyApp.xcarchive -exportPath ./build -exportOptionsPlist ExportOptions.plist # Run tests xcodebuild test -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 15 Pro'
bash rm -rf ~/Library/Developer/Xcode/DerivedData
bash security find-identity -v -p codesigning
bash swift package resolve # Or in Xcode: File > Packages > Reset Package Caches
bash xcrun simctl erase all
ios-persistence - Core Data and Realm integrationpush-notifications - APNs configurationmobile-security - iOS security implementationapp-store-connect - App Store submission| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→pass | 15,523 | 14,649 | -6% | 1 | 1 | 0% | 2,968 | 5,088 | +71% | 0 | 0 | — |
case-02 | fail→pass | 17,497 | 15,134 | -14% | 1 | 1 | 0% | 3,577 | 5,706 | +60% | 0 | 0 | — |
case-03 | pass→pass | 6,255 | 5,870 | -6% | 1 | 1 | 0% | 1,324 | 3,839 | +190% | 0 | 0 | — |
case-04 | pass→pass | 4,292 | 5,163 | +20% | 1 | 1 | 0% | 775 | 3,465 | +347% | 0 | 0 | — |
case-05 | pass→pass | 12,077 | 9,979 | -17% | 1 | 1 | 0% | 1,851 | 4,280 | +131% | 0 | 0 | — |
case-06 | pass→pass | 11,153 | 11,658 | +5% | 1 | 1 | 0% | 2,177 | 4,723 | +117% | 0 | 0 | — |
case-07 | pass→pass | 6,711 | 3,589 | -47% | 1 | 1 | 0% | 1,049 | 3,208 | +206% | 0 | 0 | — |
case-08 | pass→pass | 2,436 | 4,082 | +68% | 1 | 1 | 0% | 412 | 3,150 | +665% | 0 | 0 | — |
case-09 | pass→pass | 4,992 | 3,845 | -23% | 1 | 1 | 0% | 936 | 3,141 | +236% | 0 | 0 | — |
case-10 | pass→pass | 6,033 | 8,324 | +38% | 1 | 1 | 0% | 1,154 | 4,021 | +248% | 0 | 0 | — |
case-11 | pass→pass | 3,536 | 4,593 | +30% | 1 | 1 | 0% | 682 | 3,228 | +373% | 0 | 0 | — |
case-12 | pass→pass | 6,736 | 4,940 | -27% | 1 | 1 | 0% | 1,088 | 3,421 | +214% | 0 | 0 | — |
case-13 | pass→pass | 5,040 | 6,469 | +28% | 1 | 1 | 0% | 907 | 3,730 | +311% | 0 | 0 | — |
case-14 | pass→pass | 10,218 | 6,295 | -38% | 1 | 1 | 0% | 1,790 | 3,414 | +91% | 0 | 0 | — |
case-15 | pass→pass | 3,921 | 4,488 | +14% | 1 | 1 | 0% | 524 | 3,170 | +505% | 0 | 0 | — |
case-16 | pass→pass | 5,683 | 6,291 | +11% | 1 | 1 | 0% | 1,082 | 3,511 | +224% | 0 | 0 | — |
case-17 | pass→pass | 3,445 | 4,426 | +28% | 1 | 1 | 0% | 662 | 3,172 | +379% | 0 | 0 | — |
case-18 | pass→pass | 9,443 | 11,049 | +17% | 1 | 1 | 0% | 2,024 | 4,310 | +113% | 0 | 0 | — |
case-19 | pass→pass | 8,998 | 7,531 | -16% | 1 | 1 | 0% | 1,574 | 3,755 | +139% | 0 | 0 | — |
case-20 | pass→pass | 9,884 | 9,416 | -5% | 1 | 1 | 0% | 2,012 | 4,375 | +117% | 0 | 0 | — |
case-21 | pass→pass | 9,883 | 11,712 | +19% | 1 | 1 | 0% | 2,132 | 5,060 | +137% | 0 | 0 | — |
case-22 | pass→pass | 14,552 | 14,285 | -2% | 1 | 1 | 0% | 2,426 | 4,867 | +101% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +5 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.