swift-fundamentals

Comprehensive guide to Swift 6.x language features, best practices, macros, and project configuration for iOS 26 and macOS Tahoe development.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "swift-fundamentals" with this command: npx skills add bluewaves-creations/bluewaves-skills/bluewaves-creations-bluewaves-skills-swift-fundamentals

Swift Fundamentals

Comprehensive guide to Swift 6.x language features, best practices, macros, and project configuration for iOS 26 and macOS Tahoe development.

Prerequisites

  • Xcode 26+ or Swift 6.x toolchain

  • macOS 15.5+ (Sequoia) for full iOS 26 support

Swift Version Check

swift --version

Swift version 6.x

Swift 6.x Key Features

Swift 6.0 - Major Changes

  • Complete Concurrency Checking - Strict data-race safety by default

  • Typed Throws - Functions can specify error types: throws(MyError)

  • Noncopyable Types - ~Copyable for unique ownership

  • Pack Iteration - Iterate over parameter packs

  • 128-bit Integer Types - Int128 and UInt128

  • count(where:) - Count elements matching predicate

Swift 6.2 - Recent Improvements

  • Approachable Concurrency - Easier adoption path

  • Single-threaded by default - New defaultIsolation setting

  • Observations Async Sequence - Stream state changes

  • Pre-built swift-syntax - Faster macro compilation

  • InlineArray - Fixed-size inline storage

Swift 6.3 - Latest (2025)

  • Enhanced Type Inference - Better generic inference

  • Improved Error Messages - Clearer diagnostics

  • Performance Optimizations - Faster compilation

Core Macros

@Observable (iOS 17+)

Modern replacement for ObservableObject . Automatically tracks property access.

import Observation

@Observable class UserSettings { var username: String = "" var isLoggedIn: Bool = false var preferences: Preferences = Preferences()

// Computed properties are also tracked
var displayName: String {
    isLoggedIn ? username : "Guest"
}

}

// Usage in SwiftUI struct SettingsView: View { var settings: UserSettings // No @ObservedObject needed

var body: some View {
    Text(settings.displayName)
    // View automatically updates when displayName changes
}

}

Key Differences from ObservableObject:

  • No @Published property wrappers needed

  • No objectWillChange publisher

  • Finer-grained updates (per-property, not whole object)

  • Use @Bindable for two-way bindings

struct EditView: View { @Bindable var settings: UserSettings

var body: some View {
    TextField("Username", text: $settings.username)
}

}

@Model (SwiftData)

Declares a SwiftData model with automatic persistence.

import SwiftData

@Model class Note { var title: String var content: String var createdAt: Date var tags: [Tag]? // Optional relationship for CloudKit

init(title: String, content: String = "") {
    self.title = title
    self.content = content
    self.createdAt = Date()
}

}

@Model class Tag { var name: String var notes: [Note]? // Inverse relationship

init(name: String) {
    self.name = name
}

}

Important for CloudKit Sync:

  • All relationships must be optional

  • No @Attribute(.unique) constraints

  • Default values required for non-optional properties

@MainActor

Ensures code runs on the main thread/actor.

@MainActor class ViewModel { var items: [Item] = [] var isLoading = false

func loadItems() async {
    isLoading = true
    defer { isLoading = false }

    // Network call can be off main actor
    let fetched = await fetchItems()

    // Assignment happens on main actor
    items = fetched
}

nonisolated func fetchItems() async -> [Item] {
    // This can run on any thread
    try? await URLSession.shared.data(from: url)
    // ...
}

}

@Generable (Foundation Models - iOS 26)

Enables structured AI output generation.

import FoundationModels

@Generable struct MovieRecommendation { var title: String var year: Int var genre: String var reason: String }

// Usage let session = LanguageModelSession() let recommendation: MovieRecommendation = try await session.respond( to: "Recommend a sci-fi movie from the 2020s" )

@Test (Swift Testing)

Marks a function as a test case.

import Testing

@Test("User can create account with valid email") func createAccountWithValidEmail() async throws { let result = try await authService.createAccount(email: "test@example.com") #expect(result.success) #expect(result.user?.email == "test@example.com") }

@Test("Password validation", arguments: [ ("abc", false), ("abc12345", true), ("ABC12345!", true) ]) func validatePassword(password: String, expected: Bool) { #expect(validator.isValid(password) == expected) }

Property Wrappers

SwiftUI Property Wrappers

struct ContentView: View { // Local state - view owns this value @State private var count = 0

// Two-way binding from parent
@Binding var selectedTab: Int

// Environment value from system or parent
@Environment(\.colorScheme) var colorScheme

// Custom environment object
@Environment(AppState.self) var appState

// SwiftData query
@Query(sort: \Note.createdAt, order: .reverse)
var notes: [Note]

// Focus state for text fields
@FocusState private var isFocused: Bool

// Namespace for matched geometry effects
@Namespace private var animation

var body: some View {
    // ...
}

}

@Bindable (iOS 17+)

Creates bindings to @Observable properties.

struct EditorView: View { @Bindable var document: Document // Document is @Observable

var body: some View {
    TextEditor(text: $document.content)
    Toggle("Published", isOn: $document.isPublished)
}

}

@AppStorage

Persists values to UserDefaults.

struct SettingsView: View { @AppStorage("hasCompletedOnboarding") var hasCompletedOnboarding = false @AppStorage("preferredTheme") var preferredTheme = "system" @AppStorage("notificationsEnabled") var notificationsEnabled = true

var body: some View {
    Toggle("Notifications", isOn: $notificationsEnabled)
}

}

@SceneStorage

Persists view state per scene (for state restoration).

struct DocumentView: View { @SceneStorage("selectedDocumentID") var selectedDocumentID: String? @SceneStorage("scrollPosition") var scrollPosition: Double = 0

var body: some View {
    // State restored when scene is recreated
}

}

Package.swift Configuration

Basic Package

// swift-tools-version: 6.0 import PackageDescription

let package = Package( name: "MyApp", platforms: [ .iOS(.v26), .macOS(.v26) ], products: [ .library(name: "MyApp", targets: ["MyApp"]) ], dependencies: [ // External dependencies ], targets: [ .target( name: "MyApp", dependencies: [], swiftSettings: [ .enableExperimentalFeature("StrictConcurrency") ] ), .testTarget( name: "MyAppTests", dependencies: ["MyApp"] ) ] )

With Dependencies

// swift-tools-version: 6.0 import PackageDescription

let package = Package( name: "MyApp", platforms: [ .iOS(.v26), .macOS(.v26) ], products: [ .library(name: "MyApp", targets: ["MyApp"]) ], dependencies: [ .package(url: "https://github.com/apple/swift-algorithms", from: "1.2.0"), .package(url: "https://github.com/apple/swift-collections", from: "1.1.0"), .package(url: "https://github.com/apple/swift-async-algorithms", from: "1.0.0") ], targets: [ .target( name: "MyApp", dependencies: [ .product(name: "Algorithms", package: "swift-algorithms"), .product(name: "Collections", package: "swift-collections"), .product(name: "AsyncAlgorithms", package: "swift-async-algorithms") ] ) ] )

Strict Concurrency Settings

swiftSettings: [ // Full Swift 6 concurrency .enableExperimentalFeature("StrictConcurrency"),

// Or gradual adoption
.swiftLanguageMode(.v6),

// Enable upcoming features
.enableUpcomingFeature("ExistentialAny"),
.enableUpcomingFeature("InternalImportsByDefault")

]

Project Structure

Recommended Layout

MyApp/ ├── Package.swift ├── Sources/ │ └── MyApp/ │ ├── App/ │ │ ├── MyAppApp.swift │ │ └── AppState.swift │ ├── Models/ │ │ ├── Note.swift │ │ ├── Tag.swift │ │ └── User.swift │ ├── Views/ │ │ ├── ContentView.swift │ │ ├── Notes/ │ │ │ ├── NoteListView.swift │ │ │ ├── NoteDetailView.swift │ │ │ └── NoteEditorView.swift │ │ └── Settings/ │ │ └── SettingsView.swift │ ├── Services/ │ │ ├── NetworkService.swift │ │ └── StorageService.swift │ ├── Utilities/ │ │ ├── Extensions/ │ │ └── Helpers/ │ └── Resources/ │ ├── Localizable.xcstrings │ └── Assets.xcassets └── Tests/ └── MyAppTests/ ├── ModelTests/ ├── ServiceTests/ └── ViewTests/

App Entry Point

import SwiftUI import SwiftData

@main struct MyAppApp: App { var body: some Scene { WindowGroup { ContentView() } .modelContainer(for: [Note.self, Tag.self]) } }

With Custom Container Configuration

@main struct MyAppApp: App { let container: ModelContainer

init() {
    let schema = Schema([Note.self, Tag.self])
    let config = ModelConfiguration(
        schema: schema,
        isStoredInMemoryOnly: false,
        cloudKitDatabase: .automatic  // Enable iCloud sync
    )

    do {
        container = try ModelContainer(for: schema, configurations: config)
    } catch {
        fatalError("Failed to configure SwiftData: \(error)")
    }
}

var body: some Scene {
    WindowGroup {
        ContentView()
    }
    .modelContainer(container)
}

}

Modern Swift Patterns

Result Builders

@resultBuilder struct HTMLBuilder { static func buildBlock(_ components: String...) -> String { components.joined() }

static func buildOptional(_ component: String?) -> String {
    component ?? ""
}

static func buildEither(first component: String) -> String {
    component
}

static func buildEither(second component: String) -> String {
    component
}

}

func html(@HTMLBuilder content: () -> String) -> String { "<html>(content())</html>" }

let page = html { "<head><title>Hello</title></head>" "<body>" if showHeader { "<h1>Welcome</h1>" } "<p>Content here</p>" "</body>" }

Typed Throws (Swift 6)

enum NetworkError: Error { case invalidURL case noData case decodingFailed }

func fetchUser(id: Int) throws(NetworkError) -> User { guard let url = URL(string: "https://api.example.com/users/\(id)") else { throw .invalidURL } // ... }

// Caller knows exactly what errors to handle do { let user = try fetchUser(id: 123) } catch .invalidURL { // Handle invalid URL } catch .noData { // Handle no data } catch .decodingFailed { // Handle decoding error }

Noncopyable Types (Swift 6)

struct UniqueResource: ~Copyable { let handle: Int

init(handle: Int) {
    self.handle = handle
}

deinit {
    // Clean up resource
    closeHandle(handle)
}

consuming func close() {
    // Explicitly consume the resource
}

}

func useResource() { let resource = UniqueResource(handle: 42) // resource cannot be copied // processResource(resource) // This moves resource // resource.doSomething() // Error: resource was moved }

Parameter Packs (Swift 6)

func all<each T: Equatable>( _ values: repeat each T, equalTo comparisons: repeat each T ) -> Bool { for (value, comparison) in repeat (each values, each comparisons) { if value != comparison { return false } } return true }

let result = all(1, "hello", true, equalTo: 1, "hello", true) // true

Error Handling Best Practices

Define Domain Errors

enum AppError: LocalizedError { case networkUnavailable case unauthorized case notFound(resource: String) case validationFailed(field: String, reason: String) case unknown(underlying: Error)

var errorDescription: String? {
    switch self {
    case .networkUnavailable:
        return "Network connection unavailable"
    case .unauthorized:
        return "You are not authorized to perform this action"
    case .notFound(let resource):
        return "\(resource) was not found"
    case .validationFailed(let field, let reason):
        return "\(field): \(reason)"
    case .unknown(let error):
        return error.localizedDescription
    }
}

}

Result Type Pattern

func fetchData() async -> Result<Data, AppError> { guard NetworkMonitor.shared.isConnected else { return .failure(.networkUnavailable) }

do {
    let data = try await networkService.fetch()
    return .success(data)
} catch {
    return .failure(.unknown(underlying: error))
}

}

// Usage switch await fetchData() { case .success(let data): process(data) case .failure(let error): showError(error) }

Extensions Best Practices

Organize by Functionality

// String+Validation.swift extension String { var isValidEmail: Bool { let pattern = #"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,}$"# return range(of: pattern, options: .regularExpression) != nil }

var isValidPassword: Bool {
    count >= 8 &#x26;&#x26;
    range(of: "[A-Z]", options: .regularExpression) != nil &#x26;&#x26;
    range(of: "[0-9]", options: .regularExpression) != nil
}

}

// Date+Formatting.swift extension Date { var relativeDescription: String { let formatter = RelativeDateTimeFormatter() formatter.unitsStyle = .short return formatter.localizedString(for: self, relativeTo: Date()) }

var iso8601String: String {
    ISO8601DateFormatter().string(from: self)
}

}

// View+Modifiers.swift extension View { func cardStyle() -> some View { modifier(CardModifier()) }

@ViewBuilder
func `if`&#x3C;Content: View>(_ condition: Bool, transform: (Self) -> Content) -> some View {
    if condition {
        transform(self)
    } else {
        self
    }
}

}

Code Quality

SwiftLint Configuration

.swiftlint.yml

included:

  • Sources
  • Tests

excluded:

  • .build
  • Package.swift

disabled_rules:

  • trailing_whitespace
  • line_length

opt_in_rules:

  • empty_count
  • explicit_init
  • closure_spacing
  • overridden_super_call
  • redundant_nil_coalescing
  • private_outlet
  • nimble_operator
  • attributes
  • operator_usage_whitespace
  • closure_end_indentation
  • first_where
  • object_literal
  • number_separator
  • prohibited_super_call
  • fatal_error_message
  • weak_delegate

line_length: warning: 120 error: 200

type_body_length: warning: 300 error: 500

file_length: warning: 500 error: 1000

identifier_name: min_length: 2 max_length: 50

Swift Format Configuration

// .swift-format { "version": 1, "lineLength": 120, "indentation": { "spaces": 4 }, "tabWidth": 4, "maximumBlankLines": 1, "respectsExistingLineBreaks": true, "lineBreakBeforeControlFlowKeywords": false, "lineBreakBeforeEachArgument": false }

Official Resources

  • The Swift Programming Language

  • Swift Evolution

  • Swift 6.0 Release Notes

  • Swift 6.2 Release Notes

  • Swift Package Manager Documentation

  • Swift API Design Guidelines

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

macos-development

No summary provided by upstream source.

Repository SourceNeeds Review
General

photographer-testino

No summary provided by upstream source.

Repository SourceNeeds Review
General

photographer-lindbergh

No summary provided by upstream source.

Repository SourceNeeds Review
General

photographer-lachapelle

No summary provided by upstream source.

Repository SourceNeeds Review