Skip to content
Development
Skill

/swift-dev

Native iOS and macOS apps in Swift 6 - SwiftUI, SwiftData, concurrency, Swift Testing, XcodeGen projects, CallKit and audio sessions, App Intents and the Action Button, devices, TestFlight, notarization. Use for any iPhone or Mac app work.

BOOST
From plugin
tenequm-skills
3732 skills
Install
$ npx -y skills add tenequm/skills --skill swift-dev --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/swift-dev

Context preview

The summary Claude sees to decide when to auto-load this skill.

Native iOS and macOS apps in Swift 6 - SwiftUI, SwiftData, concurrency, Swift Testing, XcodeGen projects, CallKit and audio sessions, App Intents and the Action Button, devices, TestFlight, notarization. Use for any iPhone or Mac app work.

SKILL.md

swift-dev.SKILL.md
name: swift-dev
description: Native iOS and macOS apps in Swift 6 - SwiftUI, SwiftData, concurrency, Swift Testing, XcodeGen projects, CallKit and audio sessions, App Intents and the Action Button, devices, TestFlight, notarization. Use for any iPhone or Mac app work.
metadata:
  version: "0.1.0"
  categories: "development"
  topics: "swift, swiftui, ios, macos, xcode"
  upstream: "swift@6.4, xcode@27.0, ios@27.0, macos@27.0"
  openclaw:
    homepage: https://github.com/tenequm/skills/tree/main/skills/swift-dev
    emoji: "🍎"
    os:
      - macos

Swift Apple Development (iOS + macOS)

Native apps for iPhone and Mac with Swift 6.4 and Xcode 27.0 (iOS 27.0 and macOS 27.0 SDKs). Xcode 27 runs only on Apple silicon and needs macOS 26.6 or later. Deployment targets: iOS 17 / macOS 14 for `@Observable` and SwiftData; iOS 26 / macOS 26 for Liquid Glass, Foundation Models, `IntentModes` and `Observations`.

This file is the platform-neutral core plus a router. Load a reference only when the task needs it - the [Platform](#platform) tables say which.

Start here

| Task | Default | |------|---------| | New iOS app | XcodeGen `project.yml` (generated `.xcodeproj` gitignored) + logic in a local SPM package - `ios-project-setup.md` | | New Mac app | XcodeGen for a full app; a bare SPM executable only for CLIs and small agents (manual `.app` assembly in `spm-and-builds.md`) | | Logic, models, networking | A local SPM package with `platforms: [.iOS(.v26), .macOS(.v15)]`, tested with `swift test` on the Mac - no simulator | | Run on an iPhone | `ios-devices-and-signing.md` (Developer Mode, `devicectl`, automatic signing flags) | | Ship | iOS: `ios-distribution.md` (TestFlight, App Store). Mac: `macos-distribution.md` (Developer ID + notarization, Mac App Store) |

SPM alone cannot produce an iOS `.app` - an app target needs an Xcode project, which is why XcodeGen generates one. XcodeGen traps (details and fixes in `ios-project-setup.md`):

  • Files added after `xcodegen generate` are silently left out of the build (even with syntax errors) until you regenerate - use the `syncedFolder` source type or regenerate before every build.
  • The generated Info.plist hardcodes version 1.0 (1) and ignores `MARKETING_VERSION` / `CURRENT_PROJECT_VERSION` unless you map them in `info.properties`.
  • Gitignoring all of `*.xcodeproj/` also drops `Package.resolved`, so clean clones float to the newest dependency versions. Keep that one file committed.
  • XcodeGen's defaults are `SWIFT_VERSION 5.0` and iPhone+iPad; set both explicitly.

Build and test from the command line

swift test --package-path Core                      # logic, on the Mac, seconds
xcodegen generate                                   # project.yml -> App.xcodeproj
xcodebuild -project App.xcodeproj -scheme App \
  -destination 'generic/platform=iOS' CODE_SIGNING_ALLOWED=NO build   # compile check, no signing
xcodebuild -project App.xcodeproj -scheme App \
  -destination 'platform=iOS Simulator,name=iPhone 17' test           # needs a simulator runtime
xcrun simctl list runtimes                          # empty on a fresh Xcode
xcodebuild -downloadPlatform iOS                    # installs the iOS simulator runtime (GBs)
xcrun devicectl list devices                        # simulators and paired iPhones

Simulator.app is called DeviceHub.app in Xcode 27. CallKit does not work in the Simulator - gate it with `#if targetEnvironment(simulator)`.

Concurrency (Swift 6 language mode)

Swift 6 mode makes data races compile errors. Two module-level defaults decide most of the friction:

// Package.swift target settings
swiftSettings: [
    .swiftLanguageMode(.v6),
    .defaultIsolation(MainActor.self),   // app targets: everything is @MainActor unless marked
]

In Xcode the same is `SWIFT_VERSION = 6` and `SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor` (plus `SWIFT_APPROACHABLE_CONCURRENCY = YES`, which the Xcode 27 app template sets). `SWIFT_STRICT_CONCURRENCY` does nothing in Swift 6 mode - checking is already complete. Make app targets MainActor by default; leave library packages nonisolated. Misspelled `enableUpcomingFeature` names are silently ignored.

nonisolated struct Report: Decodable {               // see the conformance trap below
    let title: String
}

@concurrent
func decode(_ data: Data) async throws -> Report {   // always runs off the caller's actor
    try JSONDecoder().decode(Report.self, from: data)
}

actor Cache {                                          // mutable shared state
    private var items: [URL: Data] = [:]
    func value(for url: URL) -> Data? { items[url] }
    func store(_ data: Data, for url: URL) { items[url] = data }
}
  • **Conformance trap under MainActor default isolation**: a type's `Codable`/`Hashable` conformances become main-actor isolated, so decoding it in `@concurrent` code (or storing it with `@Attribute(.codable)`) fails with `main actor-isolated conformance of 'Report' to 'Decodable' cannot be used in @concurrent context`. Declare plain data types `nonisolated struct`.
  • A plain `nonisolated async` function runs on the caller's actor (Swift 6.2+ behavior). Use `@concurrent` when you need it off the main actor.
  • Value types of Sendable members are implicitly `Sendable`; a `final class` with only `let` Sendable properties can declare it. Otherwise use an `actor` or `Mutex` (Synchronization).
  • Typed throws: `func load() async throws(LoadError) -> T` gives callers an exhaustive `catch`; use it for domain errors you map at a boundary, not for everything.

Bridging delegates into a `@MainActor` class

CallKit, AVFoundation and SDK delegates call back on their own queues. Mark the delegate methods `nonisolated`, then get back onto the main actor:

@MainActor @Observable
final class CallController: NSObject, CXProviderDelegate {
    private let provider: CXProvider

    override init() {
        provider = CXProvider(configuration: CXProviderConf
Read more
Ships withtenequm-skills

Claude Code skills for founders, developers, and web3 builders. This repository publishes reusable skill folders under skills//, ships stable bundle downloads through GitHub Releases, and publishes changed skills to ClawHub.

Get the whole plugin
Stats
38
Stars
1
Forks
Active
Maintenance
Python
Language
MIT
License
3d ago
Last commit
11mo ago
Created

Repo: tenequm/skills

Other skills on tenequm-skills.