> axiom-swift-modern
Use when reviewing or generating Swift code for modern idiom correctness — catches outdated APIs, pre-Swift 5.5 patterns, and Foundation legacy usage that Claude defaults to
curl "https://skillshub.wtf/CharlesWiltgen/Axiom/axiom-swift-modern?format=md"Modern Swift Idioms
Purpose
Claude frequently generates outdated Swift patterns from its training data. This skill corrects the most common ones — patterns that compile fine but use legacy APIs when modern equivalents are clearer, more efficient, or more correct.
Philosophy: "Don't repeat what LLMs already know — focus on edge cases, surprises, soft deprecations." (Paul Hudson)
Modern API Replacements
| Old Pattern | Modern Swift | Since | Why |
|---|---|---|---|
Date() | Date.now | 5.6 | Clearer intent |
filter { }.count | count(where:) | 5.0 | Single pass, no intermediate allocation |
replacingOccurrences(of:with:) | replacing(_:with:) | 5.7 | Swift native, no Foundation bridge |
CGFloat | Double | 5.5 | Implicit bridging; exceptions: optionals, inout, ObjC-bridged APIs |
Task.sleep(nanoseconds:) | Task.sleep(for: .seconds(1)) | 5.7 | Type-safe Duration API |
DateFormatter() | .formatted() / FormatStyle | 5.5 | No instance management, localizable by default |
String(format: "%.2f", val) | val.formatted(.number.precision(.fractionLength(2))) | 5.5 | Type-safe, localized |
localizedCaseInsensitiveContains() | localizedStandardContains() | 5.0 | Handles diacritics, ligatures, width variants |
"\(firstName) \(lastName)" | PersonNameComponents with .formatted() | 5.5 | Respects locale name ordering |
"yyyy-MM-dd" with DateFormatter | try Date(string, strategy: .iso8601) | 5.6 | Modern parsing (throws); use "y" not "yyyy" for display |
contains() on user input | localizedStandardContains() | 5.0 | Required for correct text search/filtering |
Modern Syntax
| Old Pattern | Modern Swift | Since |
|---|---|---|
if let value = value { | if let value { | 5.7 |
Explicit return in single-expression | Omit return; if/switch are expressions | 5.9 |
Circle() in modifiers | .circle (static member lookup) | 5.5 |
import UIKit alongside import SwiftUI | Often not needed — SwiftUI re-exports most UIKit/AppKit types. Retain for UIKit-only APIs (UIApplication, etc.) | 5.5 |
Foundation Modernization
| Old Pattern | Modern Foundation | Since |
|---|---|---|
FileManager.default.urls(for: .documentDirectory, ...) | URL.documentsDirectory | 5.7 |
url.appendingPathComponent("file") | url.appending(path: "file") | 5.7 |
books.sorted { $0.author < $1.author } (repeated) | Conform to Comparable, call .sorted() | — |
"yyyy" in date format for display | "y" — correct in all calendar systems | — |
SwiftUI Convenience APIs Claude Misses
ContentUnavailableView.search(text: searchText)(iOS 17+) automatically includes the search term — no need to compose a custom stringLabeledContentin Forms (iOS 16+) provides consistent label alignment without manual HStack layoutconfirmationDialog()must attach to triggering UI — Liquid Glass morphing animations depend on the source element
Common Claude Hallucinations
These patterns appear frequently in Claude-generated code:
- Creates
DateFormatterinstances inline — Use.formatted()orFormatStyleinstead. If a formatter must exist, make itstatic let. - Uses
DispatchQueue.main.async— Use@MainActororMainActor.run. Never GCD. (Seeaxiom-swift-concurrencyfor full guidance.) - Uses
CGFloatfor SwiftUI parameters —Doubleworks everywhere since Swift 5.5 implicit bridging. - Generates
guard let x = x else— Useguard let x elseshorthand. - Returns explicitly in single-expression computed properties — Omit
return.
Resources
Skills: axiom-swift-performance, axiom-swift-concurrency, axiom-swiftui-architecture
> related_skills --same-repo
> axiom-eventkit
Use when working with ANY calendar event, reminder, EventKit permission, or EventKitUI controller. Covers access tiers (no-access, write-only, full), permission migration from pre-iOS 17, store lifecycle, reminder patterns, EventKitUI controller selection, Siri Event Suggestions, virtual conference extensions.
> axiom-eventkit-ref
Use when needing EventKit API details — EKEventStore, EKEvent, EKReminder, EventKitUI view controllers, EKCalendarChooser, authorization methods, predicate-based fetching, recurrence rules, Siri Event Suggestions donation, EKVirtualConferenceProvider, location-based reminders, and EKErrorDomain codes
> axiom-contacts
Use when accessing ANY contact data, requesting Contacts permissions, choosing between picker and store access, implementing Contact Access Button, or migrating to iOS 18 limited access. Covers authorization levels, CNContactStore, ContactProvider, key fetching, incremental sync.
> axiom-contacts-ref
Use when needing Contacts API details — CNContactStore, CNMutableContact, CNSaveRequest, CNContactFormatter, CNContactVCardSerialization, CNContactPickerViewController, ContactAccessButton, contactAccessPicker, ContactProvider extension, CNChangeHistoryFetchRequest, contact key descriptors, and CNError codes