buildanything 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +55 -0
- package/README.md +71 -61
- package/agents/ios-app-review-guardian.md +49 -0
- package/agents/ios-foundation-models-specialist.md +46 -0
- package/agents/ios-storekit-specialist.md +52 -0
- package/agents/ios-swift-architect.md +102 -0
- package/agents/ios-swift-search.md +130 -0
- package/agents/ios-swift-ui-design.md +104 -0
- package/commands/build.md +80 -176
- package/commands/fix.md +65 -0
- package/commands/setup.md +73 -0
- package/commands/ux-review.md +63 -0
- package/commands/verify.md +72 -0
- package/hooks/session-start +18 -1
- package/package.json +5 -2
- package/protocols/brainstorm.md +99 -0
- package/protocols/build-fix.md +52 -0
- package/protocols/cleanup.md +54 -0
- package/protocols/design.md +269 -0
- package/protocols/eval-harness.md +61 -0
- package/protocols/fake-data-detector.md +64 -0
- package/protocols/ios-context.md +235 -0
- package/protocols/ios-frameworks-map.md +323 -0
- package/protocols/ios-phase-branches.md +162 -0
- package/protocols/ios-preflight.md +27 -0
- package/protocols/metric-loop.md +93 -0
- package/protocols/planning.md +87 -0
- package/protocols/smoke-test.md +110 -0
- package/protocols/verify.md +67 -0
- package/protocols/web-phase-branches.md +201 -0
- package/skills/ios/_VENDORED.md +60 -0
- package/skills/ios/activitykit/LICENSE +131 -0
- package/skills/ios/activitykit/SKILL.md +505 -0
- package/skills/ios/activitykit/references/activitykit-patterns.md +868 -0
- package/skills/ios/app-intents/LICENSE +131 -0
- package/skills/ios/app-intents/SKILL.md +494 -0
- package/skills/ios/app-intents/references/appintents-advanced.md +1076 -0
- package/skills/ios/apple-on-device-ai/LICENSE +131 -0
- package/skills/ios/apple-on-device-ai/SKILL.md +505 -0
- package/skills/ios/apple-on-device-ai/references/coreml-conversion.md +425 -0
- package/skills/ios/apple-on-device-ai/references/coreml-optimization.md +344 -0
- package/skills/ios/apple-on-device-ai/references/foundation-models.md +508 -0
- package/skills/ios/apple-on-device-ai/references/mlx-swift.md +285 -0
- package/skills/ios/ios-26-platform/SKILL.md +53 -0
- package/skills/ios/ios-26-platform/references/automatic-adoption.md +161 -0
- package/skills/ios/ios-26-platform/references/backward-compat.md +238 -0
- package/skills/ios/ios-26-platform/references/liquid-glass.md +255 -0
- package/skills/ios/ios-26-platform/references/swiftui-apis.md +277 -0
- package/skills/ios/ios-26-platform/references/toolbar-navigation.md +250 -0
- package/skills/ios/ios-bootstrap/SKILL.md +98 -0
- package/skills/ios/ios-bootstrap/references/apple-docs-mcp-config.md +28 -0
- package/skills/ios/ios-bootstrap/references/new-project-dialog.md +41 -0
- package/skills/ios/ios-bootstrap/references/xcode-mcp-config.md +29 -0
- package/skills/ios/ios-debugger-agent/LICENSE +21 -0
- package/skills/ios/ios-debugger-agent/SKILL.md +58 -0
- package/skills/ios/ios-debugger-agent/agents/openai.yaml +4 -0
- package/skills/ios/ios-entitlements-generator/SKILL.md +47 -0
- package/skills/ios/ios-hig/SKILL.md +41 -0
- package/skills/ios/ios-hig/references/accessibility.md +81 -0
- package/skills/ios/ios-hig/references/content.md +142 -0
- package/skills/ios/ios-hig/references/feedback.md +123 -0
- package/skills/ios/ios-hig/references/interaction.md +199 -0
- package/skills/ios/ios-hig/references/performance-platform.md +129 -0
- package/skills/ios/ios-hig/references/privacy-permissions.md +181 -0
- package/skills/ios/ios-hig/references/visual-design.md +84 -0
- package/skills/ios/ios-info-plist-hardening/SKILL.md +130 -0
- package/skills/ios/ios-maestro-flow-author/SKILL.md +68 -0
- package/skills/ios/ios-maestro-flow-author/references/input-and-scroll.yaml +17 -0
- package/skills/ios/ios-maestro-flow-author/references/modal-and-dismiss.yaml +14 -0
- package/skills/ios/ios-maestro-flow-author/references/onboarding-flow.yaml +16 -0
- package/skills/ios/ios-maestro-flow-author/references/tab-navigation.yaml +13 -0
- package/skills/ios/ios-maestro-flow-author/references/tap-and-assert.yaml +9 -0
- package/skills/ios/swift-accessibility/LICENSE +21 -0
- package/skills/ios/swift-accessibility/SKILL.md +371 -0
- package/skills/ios/swift-accessibility/examples/before-after-appkit.md +446 -0
- package/skills/ios/swift-accessibility/examples/before-after-swiftui.md +441 -0
- package/skills/ios/swift-accessibility/examples/before-after-uikit.md +464 -0
- package/skills/ios/swift-accessibility/references/assistive-access.md +441 -0
- package/skills/ios/swift-accessibility/references/display-settings.md +491 -0
- package/skills/ios/swift-accessibility/references/dynamic-type.md +420 -0
- package/skills/ios/swift-accessibility/references/media-accessibility.md +421 -0
- package/skills/ios/swift-accessibility/references/motor-input.md +393 -0
- package/skills/ios/swift-accessibility/references/nutrition-labels.md +362 -0
- package/skills/ios/swift-accessibility/references/platform-specifics.md +515 -0
- package/skills/ios/swift-accessibility/references/semantic-structure.md +585 -0
- package/skills/ios/swift-accessibility/references/testing-auditing.md +507 -0
- package/skills/ios/swift-accessibility/references/voice-control.md +317 -0
- package/skills/ios/swift-accessibility/references/voiceover-swiftui.md +584 -0
- package/skills/ios/swift-accessibility/references/voiceover-uikit.md +519 -0
- package/skills/ios/swift-accessibility/references/wcag-mapping.md +167 -0
- package/skills/ios/swift-accessibility/resources/audit-template.swift +128 -0
- package/skills/ios/swift-accessibility/resources/qa-checklist.md +258 -0
- package/skills/ios/swift-concurrency/LICENSE +21 -0
- package/skills/ios/swift-concurrency/SKILL.md +171 -0
- package/skills/ios/swift-concurrency/references/_index.md +50 -0
- package/skills/ios/swift-concurrency/references/actors.md +660 -0
- package/skills/ios/swift-concurrency/references/async-algorithms.md +847 -0
- package/skills/ios/swift-concurrency/references/async-await-basics.md +266 -0
- package/skills/ios/swift-concurrency/references/async-sequences.md +710 -0
- package/skills/ios/swift-concurrency/references/core-data.md +560 -0
- package/skills/ios/swift-concurrency/references/glossary.md +135 -0
- package/skills/ios/swift-concurrency/references/linting.md +155 -0
- package/skills/ios/swift-concurrency/references/memory-management.md +569 -0
- package/skills/ios/swift-concurrency/references/migration.md +1104 -0
- package/skills/ios/swift-concurrency/references/performance.md +593 -0
- package/skills/ios/swift-concurrency/references/sendable.md +598 -0
- package/skills/ios/swift-concurrency/references/tasks.md +636 -0
- package/skills/ios/swift-concurrency/references/testing.md +592 -0
- package/skills/ios/swift-concurrency/references/threading.md +495 -0
- package/skills/ios/swift-security-expert/LICENSE +21 -0
- package/skills/ios/swift-security-expert/SKILL.md +470 -0
- package/skills/ios/swift-security-expert/references/biometric-authentication.md +565 -0
- package/skills/ios/swift-security-expert/references/certificate-trust.md +592 -0
- package/skills/ios/swift-security-expert/references/common-anti-patterns.md +690 -0
- package/skills/ios/swift-security-expert/references/compliance-owasp-mapping.md +537 -0
- package/skills/ios/swift-security-expert/references/credential-storage-patterns.md +721 -0
- package/skills/ios/swift-security-expert/references/cryptokit-public-key.md +505 -0
- package/skills/ios/swift-security-expert/references/cryptokit-symmetric.md +497 -0
- package/skills/ios/swift-security-expert/references/keychain-access-control.md +508 -0
- package/skills/ios/swift-security-expert/references/keychain-fundamentals.md +596 -0
- package/skills/ios/swift-security-expert/references/keychain-item-classes.md +476 -0
- package/skills/ios/swift-security-expert/references/keychain-sharing.md +458 -0
- package/skills/ios/swift-security-expert/references/migration-legacy-stores.md +727 -0
- package/skills/ios/swift-security-expert/references/secure-enclave.md +539 -0
- package/skills/ios/swift-security-expert/references/testing-security-code.md +781 -0
- package/skills/ios/swift-testing-expert/LICENSE +21 -0
- package/skills/ios/swift-testing-expert/SKILL.md +79 -0
- package/skills/ios/swift-testing-expert/references/_index.md +12 -0
- package/skills/ios/swift-testing-expert/references/async-testing-and-waiting.md +127 -0
- package/skills/ios/swift-testing-expert/references/expectations.md +145 -0
- package/skills/ios/swift-testing-expert/references/fundamentals.md +141 -0
- package/skills/ios/swift-testing-expert/references/migration-from-xctest.md +127 -0
- package/skills/ios/swift-testing-expert/references/parallelization-and-isolation.md +95 -0
- package/skills/ios/swift-testing-expert/references/parameterized-testing.md +284 -0
- package/skills/ios/swift-testing-expert/references/performance-and-best-practices.md +187 -0
- package/skills/ios/swift-testing-expert/references/traits-and-tags.md +114 -0
- package/skills/ios/swift-testing-expert/references/xcode-workflows.md +70 -0
- package/skills/ios/swiftdata-pro/LICENSE +21 -0
- package/skills/ios/swiftdata-pro/SKILL.md +102 -0
- package/skills/ios/swiftdata-pro/agents/openai.yaml +10 -0
- package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.png +0 -0
- package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.svg +29 -0
- package/skills/ios/swiftdata-pro/references/class-inheritance.md +104 -0
- package/skills/ios/swiftdata-pro/references/cloudkit.md +10 -0
- package/skills/ios/swiftdata-pro/references/core-rules.md +20 -0
- package/skills/ios/swiftdata-pro/references/indexing.md +27 -0
- package/skills/ios/swiftdata-pro/references/predicates.md +73 -0
- package/skills/ios/swiftui-design-principles/AGENTS.md +21 -0
- package/skills/ios/swiftui-design-principles/LICENSE +21 -0
- package/skills/ios/swiftui-design-principles/README.md +41 -0
- package/skills/ios/swiftui-design-principles/SKILL.md +605 -0
- package/skills/ios/swiftui-design-principles/metadata.json +10 -0
- package/skills/ios/swiftui-liquid-glass/LICENSE +21 -0
- package/skills/ios/swiftui-liquid-glass/SKILL.md +95 -0
- package/skills/ios/swiftui-liquid-glass/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-liquid-glass/references/liquid-glass.md +280 -0
- package/skills/ios/swiftui-performance-audit/LICENSE +21 -0
- package/skills/ios/swiftui-performance-audit/SKILL.md +111 -0
- package/skills/ios/swiftui-performance-audit/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-performance-audit/references/code-smells.md +150 -0
- package/skills/ios/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
- package/skills/ios/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
- package/skills/ios/swiftui-performance-audit/references/profiling-intake.md +44 -0
- package/skills/ios/swiftui-performance-audit/references/report-template.md +47 -0
- package/skills/ios/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
- package/skills/ios/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
- package/skills/ios/swiftui-pro/LICENSE +21 -0
- package/skills/ios/swiftui-pro/SKILL.md +108 -0
- package/skills/ios/swiftui-pro/agents/openai.yaml +10 -0
- package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.png +0 -0
- package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.svg +29 -0
- package/skills/ios/swiftui-pro/references/accessibility.md +13 -0
- package/skills/ios/swiftui-pro/references/api.md +39 -0
- package/skills/ios/swiftui-pro/references/data.md +43 -0
- package/skills/ios/swiftui-pro/references/design.md +31 -0
- package/skills/ios/swiftui-pro/references/hygiene.md +9 -0
- package/skills/ios/swiftui-pro/references/navigation.md +14 -0
- package/skills/ios/swiftui-pro/references/performance.md +46 -0
- package/skills/ios/swiftui-pro/references/swift.md +56 -0
- package/skills/ios/swiftui-pro/references/views.md +35 -0
- package/skills/ios/swiftui-ui-patterns/LICENSE +21 -0
- package/skills/ios/swiftui-ui-patterns/SKILL.md +100 -0
- package/skills/ios/swiftui-ui-patterns/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-ui-patterns/references/app-wiring.md +201 -0
- package/skills/ios/swiftui-ui-patterns/references/async-state.md +96 -0
- package/skills/ios/swiftui-ui-patterns/references/components-index.md +50 -0
- package/skills/ios/swiftui-ui-patterns/references/controls.md +57 -0
- package/skills/ios/swiftui-ui-patterns/references/deeplinks.md +66 -0
- package/skills/ios/swiftui-ui-patterns/references/focus.md +90 -0
- package/skills/ios/swiftui-ui-patterns/references/form.md +97 -0
- package/skills/ios/swiftui-ui-patterns/references/grids.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/haptics.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/input-toolbar.md +51 -0
- package/skills/ios/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
- package/skills/ios/swiftui-ui-patterns/references/list.md +86 -0
- package/skills/ios/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
- package/skills/ios/swiftui-ui-patterns/references/macos-settings.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/matched-transitions.md +59 -0
- package/skills/ios/swiftui-ui-patterns/references/media.md +73 -0
- package/skills/ios/swiftui-ui-patterns/references/menu-bar.md +101 -0
- package/skills/ios/swiftui-ui-patterns/references/navigationstack.md +159 -0
- package/skills/ios/swiftui-ui-patterns/references/overlay.md +45 -0
- package/skills/ios/swiftui-ui-patterns/references/performance.md +62 -0
- package/skills/ios/swiftui-ui-patterns/references/previews.md +48 -0
- package/skills/ios/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
- package/skills/ios/swiftui-ui-patterns/references/scrollview.md +87 -0
- package/skills/ios/swiftui-ui-patterns/references/searchable.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/sheets.md +155 -0
- package/skills/ios/swiftui-ui-patterns/references/split-views.md +72 -0
- package/skills/ios/swiftui-ui-patterns/references/tabview.md +114 -0
- package/skills/ios/swiftui-ui-patterns/references/theming.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/title-menus.md +93 -0
- package/skills/ios/swiftui-ui-patterns/references/top-bar.md +49 -0
- package/skills/ios/swiftui-view-refactor/LICENSE +21 -0
- package/skills/ios/swiftui-view-refactor/SKILL.md +207 -0
- package/skills/ios/swiftui-view-refactor/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-view-refactor/references/mv-patterns.md +161 -0
- package/skills/ios/widgetkit/LICENSE +131 -0
- package/skills/ios/widgetkit/SKILL.md +502 -0
- package/skills/ios/widgetkit/references/widgetkit-advanced.md +871 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// AccessibilityAuditTests.swift
|
|
2
|
+
// Drop-in XCUITest file for automated accessibility auditing.
|
|
3
|
+
// Requires a platform that supports performAccessibilityAudit().
|
|
4
|
+
// The helper methods below skip gracefully on older deployment targets.
|
|
5
|
+
//
|
|
6
|
+
// Usage:
|
|
7
|
+
// 1. Add this file to your UI test target
|
|
8
|
+
// 2. Add navigation steps for each screen in your app
|
|
9
|
+
// 3. Run tests — failures indicate accessibility issues
|
|
10
|
+
//
|
|
11
|
+
// These tests use performAccessibilityAudit() to catch:
|
|
12
|
+
// - Missing accessibility labels
|
|
13
|
+
// - Low color contrast (WCAG thresholds)
|
|
14
|
+
// - Touch targets below 44x44pt
|
|
15
|
+
// - Text that doesn't scale with Dynamic Type
|
|
16
|
+
// - Clipped or truncated text
|
|
17
|
+
// - Incorrect accessibility traits
|
|
18
|
+
|
|
19
|
+
import XCTest
|
|
20
|
+
|
|
21
|
+
final class AccessibilityAuditTests: XCTestCase {
|
|
22
|
+
|
|
23
|
+
let app = XCUIApplication()
|
|
24
|
+
|
|
25
|
+
override func setUpWithError() throws {
|
|
26
|
+
continueAfterFailure = false
|
|
27
|
+
app.launch()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// MARK: - Full Audit (All Checks)
|
|
31
|
+
|
|
32
|
+
/// Audits the launch screen with all accessibility checks.
|
|
33
|
+
/// Add one test method per key screen in your app.
|
|
34
|
+
func testLaunchScreenAccessibility() throws {
|
|
35
|
+
try performAudit()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// MARK: - Per-Screen Audits
|
|
39
|
+
//
|
|
40
|
+
// Copy this pattern for each screen. Navigate to the screen,
|
|
41
|
+
// then run the audit.
|
|
42
|
+
//
|
|
43
|
+
// func testSettingsScreenAccessibility() throws {
|
|
44
|
+
// app.tabBars.buttons["Settings"].tap()
|
|
45
|
+
// try performAudit()
|
|
46
|
+
// }
|
|
47
|
+
//
|
|
48
|
+
// func testProfileScreenAccessibility() throws {
|
|
49
|
+
// app.tabBars.buttons["Profile"].tap()
|
|
50
|
+
// try performAudit()
|
|
51
|
+
// }
|
|
52
|
+
|
|
53
|
+
// MARK: - Filtered Audits
|
|
54
|
+
|
|
55
|
+
/// Contrast and labels only — the two most common failures.
|
|
56
|
+
func testContrastAndLabels() throws {
|
|
57
|
+
try performAudit([.contrast, .sufficientElementDescription])
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/// Touch targets and element detection.
|
|
61
|
+
func testHitRegionsAndDetection() throws {
|
|
62
|
+
try performAudit([.hitRegion, .elementDetection])
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/// Dynamic Type scaling and text clipping.
|
|
66
|
+
func testDynamicTypeSupport() throws {
|
|
67
|
+
try performAudit([.dynamicType, .textClipped])
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// MARK: - Audit with Known Issue Exclusions
|
|
71
|
+
|
|
72
|
+
/// Full audit that ignores specific known issues.
|
|
73
|
+
/// Replace the example exclusion with your own.
|
|
74
|
+
func testAuditWithExclusions() throws {
|
|
75
|
+
try performAudit(.all) { issue in
|
|
76
|
+
// Example: ignore contrast issues on branded splash logo
|
|
77
|
+
// if issue.auditType == .contrast,
|
|
78
|
+
// issue.element?.identifier == "splashLogo" {
|
|
79
|
+
// return true // true = ignore this issue
|
|
80
|
+
// }
|
|
81
|
+
return false // false = fail on this issue
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// MARK: - Multi-Screen Regression Test
|
|
86
|
+
|
|
87
|
+
/// Navigates through key screens and audits each one.
|
|
88
|
+
/// Customize the navigation steps for your app's tab bar or flow.
|
|
89
|
+
func testFullAppAccessibilityRegression() throws {
|
|
90
|
+
// Screen 1: Launch / Home
|
|
91
|
+
try performAudit()
|
|
92
|
+
|
|
93
|
+
// Screen 2: Navigate to second tab (customize for your app)
|
|
94
|
+
// app.tabBars.buttons["Search"].tap()
|
|
95
|
+
// try performAudit()
|
|
96
|
+
|
|
97
|
+
// Screen 3: Navigate to third tab
|
|
98
|
+
// app.tabBars.buttons["Settings"].tap()
|
|
99
|
+
// try performAudit()
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private func performAudit(
|
|
103
|
+
_ auditTypes: XCUIAccessibilityAuditType = .all
|
|
104
|
+
) throws {
|
|
105
|
+
try requireAccessibilityAuditSupport()
|
|
106
|
+
if #available(iOS 17, macOS 14, tvOS 17, watchOS 10, visionOS 1, *) {
|
|
107
|
+
try app.performAccessibilityAudit(for: auditTypes)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private func performAudit(
|
|
112
|
+
_ auditTypes: XCUIAccessibilityAuditType = .all,
|
|
113
|
+
issueHandler: @escaping (XCUIAccessibilityAuditIssue) throws -> Bool
|
|
114
|
+
) throws {
|
|
115
|
+
try requireAccessibilityAuditSupport()
|
|
116
|
+
if #available(iOS 17, macOS 14, tvOS 17, watchOS 10, visionOS 1, *) {
|
|
117
|
+
try app.performAccessibilityAudit(for: auditTypes, issueHandler)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private func requireAccessibilityAuditSupport() throws {
|
|
122
|
+
guard #available(iOS 17, macOS 14, tvOS 17, watchOS 10, visionOS 1, *) else {
|
|
123
|
+
throw XCTSkip(
|
|
124
|
+
"performAccessibilityAudit() requires iOS 17+, macOS 14+, tvOS 17+, watchOS 10+, or visionOS 1+."
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# Accessibility QA Checklist
|
|
2
|
+
|
|
3
|
+
Standalone checklist for manual accessibility testing. Hand this to QA testers — no skill or Claude knowledge required.
|
|
4
|
+
|
|
5
|
+
Aligned with Apple's 9 App Store Accessibility Nutrition Labels and WCAG 2.2 Level AA.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## How to Use This Checklist
|
|
10
|
+
|
|
11
|
+
1. Test on a **real device** — Simulator doesn't fully support VoiceOver, Voice Control, or Switch Control
|
|
12
|
+
2. Test **every key user flow**: launch, onboarding, login, main feature, settings, purchase (if applicable)
|
|
13
|
+
3. Mark each item: Pass / Fail / N/A
|
|
14
|
+
4. A single Fail in a Nutrition Label category means that label **cannot be claimed** on the App Store
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Before You Start: Xcode Tools
|
|
19
|
+
|
|
20
|
+
### Xcode Canvas Variants (during development)
|
|
21
|
+
In the preview canvas, click the **Variants** button (grid icon) at the bottom:
|
|
22
|
+
- **Dynamic Type Variants** — renders the view at all 12 text sizes
|
|
23
|
+
- **Color Scheme Variants** — shows light and dark mode side by side
|
|
24
|
+
- **Orientation Variants** — portrait and landscape
|
|
25
|
+
|
|
26
|
+
### Xcode Canvas Device Settings (during development)
|
|
27
|
+
Click the **Device Settings** button (slider icon) at the bottom of the canvas:
|
|
28
|
+
- Set color scheme, Dynamic Type size, and orientation for a single preview
|
|
29
|
+
- Combine settings to test specific scenarios (e.g., dark mode + large text)
|
|
30
|
+
|
|
31
|
+
### Accessibility Inspector (Simulator or device)
|
|
32
|
+
Xcode menu → Open Developer Tool → Accessibility Inspector
|
|
33
|
+
- **Inspection tab** — point at any element to see its label, traits, value, and frame size
|
|
34
|
+
- **Audit tab** — run automated checks on the current screen (missing labels, low contrast, small targets)
|
|
35
|
+
- **Settings tab** — toggle Increase Contrast, Reduce Motion, Bold Text, Reduce Transparency on the Simulator without changing device settings
|
|
36
|
+
|
|
37
|
+
### performAccessibilityAudit() (automated tests)
|
|
38
|
+
Add to XCUITest target (iOS 17+). Catches missing labels, low contrast, small hit regions, clipped text, and Dynamic Type failures in CI. See `resources/audit-template.swift` for a drop-in template.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 1. VoiceOver
|
|
43
|
+
|
|
44
|
+
**Enable:** Settings → Accessibility → VoiceOver (or triple-click Side button if configured)
|
|
45
|
+
|
|
46
|
+
| # | Test | How to verify | Pass criteria |
|
|
47
|
+
|---|---|---|---|
|
|
48
|
+
| 1.1 | Navigate all elements | Swipe right repeatedly through entire screen | Every interactive element is reachable |
|
|
49
|
+
| 1.2 | Labels are meaningful | Tap each element, listen to announcement | Label describes the element concisely, not "button" or "image" |
|
|
50
|
+
| 1.3 | No redundant type in label | Listen for "button button" or "image image" | VoiceOver adds type automatically — label should not include it |
|
|
51
|
+
| 1.4 | State as traits | Toggle a switch, select a tab | VoiceOver says "selected" / "on" / "off" — not embedded in the label text |
|
|
52
|
+
| 1.5 | Decorative images hidden | Swipe through screen | Decorative images are skipped |
|
|
53
|
+
| 1.6 | Reading order is logical | Use "Read All" (two-finger swipe up) | Content reads in visual order, top-to-bottom, left-to-right |
|
|
54
|
+
| 1.7 | Focus after navigation | Push a new screen | Focus moves to first element of new screen (usually title or back button) |
|
|
55
|
+
| 1.8 | Focus after modal dismiss | Dismiss a sheet/alert | Focus returns to the element that triggered it |
|
|
56
|
+
| 1.9 | Adjustable controls work | Swipe up/down on slider or stepper | Value changes and is announced |
|
|
57
|
+
| 1.10 | Dynamic changes announced | Trigger a loading state or error | VoiceOver announces the change ("Loading complete", "Error: …") |
|
|
58
|
+
| 1.11 | Complete a key flow | Do the main task start-to-finish with VoiceOver | Task completes without sighted assistance |
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 2. Voice Control
|
|
63
|
+
|
|
64
|
+
**Enable:** Settings → Accessibility → Voice Control
|
|
65
|
+
|
|
66
|
+
| # | Test | How to verify | Pass criteria |
|
|
67
|
+
|---|---|---|---|
|
|
68
|
+
| 2.1 | Show numbers | Say "Show numbers" | Every interactive element has a number overlay |
|
|
69
|
+
| 2.2 | Tap by number | Say "Tap [number]" | Correct element activates |
|
|
70
|
+
| 2.3 | Show names | Say "Show names" | Every element shows its visible text label |
|
|
71
|
+
| 2.4 | Tap by name | Say "Tap [label]" | Element activates — label must match visible text exactly |
|
|
72
|
+
| 2.5 | Text input | Say "Type [text]" in a text field | Text is entered correctly |
|
|
73
|
+
| 2.6 | Scrolling | Say "Scroll down" / "Scroll up" | Content scrolls |
|
|
74
|
+
| 2.7 | Icon-only elements | Say "Tap Share" (or the label) for icon-only buttons | Button activates — requires `.accessibilityInputLabels` |
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 3. Larger Text (Dynamic Type)
|
|
79
|
+
|
|
80
|
+
**Enable:** Settings → Accessibility → Display & Text Size → Larger Text → drag slider to max
|
|
81
|
+
|
|
82
|
+
| # | Test | How to verify | Pass criteria |
|
|
83
|
+
|---|---|---|---|
|
|
84
|
+
| 3.1 | Text scales | Set to Accessibility 5 (max) | All text is larger |
|
|
85
|
+
| 3.2 | No clipping | Navigate all screens at max size | No text cut off without "..." affordance |
|
|
86
|
+
| 3.3 | No overlapping | Check all screens at max size | No elements overlap |
|
|
87
|
+
| 3.4 | Layout adapts | Check horizontal layouts | Rows/columns reflow to vertical when needed |
|
|
88
|
+
| 3.5 | Fixed UI chrome | Long-press on tab bar icons or toolbar items | Large Content Viewer shows enlarged version |
|
|
89
|
+
| 3.6 | Small text readable | Set to smallest size | Text is still readable |
|
|
90
|
+
|
|
91
|
+
**Quick check with Xcode:** Use Canvas Dynamic Type Variants to see all 12 sizes at once.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 4. Sufficient Contrast
|
|
96
|
+
|
|
97
|
+
**Tool:** Accessibility Inspector → Inspection tab → Color contrast
|
|
98
|
+
|
|
99
|
+
| # | Test | How to verify | Pass criteria |
|
|
100
|
+
|---|---|---|---|
|
|
101
|
+
| 4.1 | Normal text | Check body text against background | ≥ 4.5:1 contrast ratio |
|
|
102
|
+
| 4.2 | Large text | Check headings (≥ 18pt or 14pt bold) | ≥ 3:1 contrast ratio |
|
|
103
|
+
| 4.3 | Non-text elements | Check icons, borders, focus rings | ≥ 3:1 contrast ratio |
|
|
104
|
+
| 4.4 | Both modes | Repeat all checks in Dark Mode | Passes in both light and dark |
|
|
105
|
+
| 4.5 | Increased Contrast | Enable Increase Contrast in Accessibility Inspector Settings | Borders and separators become more visible |
|
|
106
|
+
| 4.6 | Placeholder text | Check text field placeholders | ≥ 4.5:1 against background |
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 5. Dark Interface
|
|
111
|
+
|
|
112
|
+
**Enable:** Settings → Display & Brightness → Dark
|
|
113
|
+
|
|
114
|
+
| # | Test | How to verify | Pass criteria |
|
|
115
|
+
|---|---|---|---|
|
|
116
|
+
| 5.1 | All text readable | Navigate all screens | No white-on-white or invisible text |
|
|
117
|
+
| 5.2 | Borders visible | Check cards, sections, separators | Borders and dividers are visible |
|
|
118
|
+
| 5.3 | Images correct | Check photos, icons | No white halo; images aren't inverted incorrectly |
|
|
119
|
+
| 5.4 | Status indicators | Check colored status elements | Still distinguishable in dark mode |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 6. Differentiate Without Color
|
|
124
|
+
|
|
125
|
+
**Enable:** Settings → Accessibility → Display & Text Size → Color Filters → Grayscale
|
|
126
|
+
|
|
127
|
+
| # | Test | How to verify | Pass criteria |
|
|
128
|
+
|---|---|---|---|
|
|
129
|
+
| 6.1 | Status indicators | Check error/success/warning states | Distinguishable by shape, icon, or text — not color alone |
|
|
130
|
+
| 6.2 | Charts and graphs | Check data visualizations | Data series distinguishable by pattern, shape, or label |
|
|
131
|
+
| 6.3 | Links | Check link text | Underlined or otherwise distinguishable from body text |
|
|
132
|
+
| 6.4 | Form validation | Trigger an error state | Error is indicated by icon or text, not just red color |
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 7. Reduced Motion
|
|
137
|
+
|
|
138
|
+
**Enable:** Settings → Accessibility → Motion → Reduce Motion
|
|
139
|
+
|
|
140
|
+
| # | Test | How to verify | Pass criteria |
|
|
141
|
+
|---|---|---|---|
|
|
142
|
+
| 7.1 | Navigation transitions | Push/pop screens | No sliding animation — dissolve or instant |
|
|
143
|
+
| 7.2 | UI animations | Trigger state changes, loading | Animations removed or replaced with fade/opacity |
|
|
144
|
+
| 7.3 | Auto-playing content | Check for auto-playing animations/video | Stopped or has manual play control |
|
|
145
|
+
| 7.4 | Parallax effects | Scroll content | No parallax or motion effects |
|
|
146
|
+
|
|
147
|
+
**Quick check:** Toggle Reduce Motion in Accessibility Inspector Settings tab while running in Simulator.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 8. Captions
|
|
152
|
+
|
|
153
|
+
**Applies to:** Apps with video or audio content
|
|
154
|
+
|
|
155
|
+
| # | Test | How to verify | Pass criteria |
|
|
156
|
+
|---|---|---|---|
|
|
157
|
+
| 8.1 | Captions available | Play a video with dialogue | Captions can be enabled via player controls |
|
|
158
|
+
| 8.2 | Auto-enable | Enable Closed Captions in Settings → Accessibility → Subtitles & Captioning | Captions appear automatically |
|
|
159
|
+
| 8.3 | Captions accurate | Read captions while watching | Captions match spoken content |
|
|
160
|
+
| 8.4 | Timing correct | Watch captions during video | Captions sync with audio |
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 9. Audio Descriptions
|
|
165
|
+
|
|
166
|
+
**Applies to:** Apps with video content where visual information is important
|
|
167
|
+
|
|
168
|
+
| # | Test | How to verify | Pass criteria |
|
|
169
|
+
|---|---|---|---|
|
|
170
|
+
| 9.1 | Audio Descriptions available | Play a video | Audio Description track can be selected |
|
|
171
|
+
| 9.2 | Auto-enable | Enable Audio Descriptions in Settings → Accessibility → Audio Descriptions | Audio Descriptions play automatically |
|
|
172
|
+
| 9.3 | Content described | Listen to Audio Descriptions | Important visual information is narrated |
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 10. Additional Checks
|
|
177
|
+
|
|
178
|
+
### Switch Control
|
|
179
|
+
|
|
180
|
+
**Enable:** Settings → Accessibility → Switch Control
|
|
181
|
+
|
|
182
|
+
| # | Test | How to verify | Pass criteria |
|
|
183
|
+
|---|---|---|---|
|
|
184
|
+
| 10.1 | Scanning | Enable auto-scan | Every element is highlighted in sequence |
|
|
185
|
+
| 10.2 | Activation | Select a highlighted element | Correct action triggers |
|
|
186
|
+
| 10.3 | Custom actions | Navigate to elements with swipe actions | Actions appear in scanning menu |
|
|
187
|
+
| 10.4 | No timeouts | Use the app slowly | Nothing times out or auto-advances |
|
|
188
|
+
|
|
189
|
+
### Full Keyboard Access (iPad / Mac)
|
|
190
|
+
|
|
191
|
+
**Enable:** Settings → Accessibility → Keyboards → Full Keyboard Access
|
|
192
|
+
|
|
193
|
+
| # | Test | How to verify | Pass criteria |
|
|
194
|
+
|---|---|---|---|
|
|
195
|
+
| 10.5 | Tab navigation | Press Tab repeatedly | Focus moves through all interactive elements |
|
|
196
|
+
| 10.6 | Reverse Tab | Press Shift+Tab | Focus moves backward |
|
|
197
|
+
| 10.7 | Activation | Press Space or Return on focused element | Element activates |
|
|
198
|
+
| 10.8 | Escape dismissal | Press Escape on modal | Modal dismisses |
|
|
199
|
+
| 10.9 | No focus traps | Tab through entire app | Focus never gets stuck |
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Summary Template
|
|
204
|
+
|
|
205
|
+
After testing, fill in:
|
|
206
|
+
|
|
207
|
+
| Nutrition Label | Status | Blocking Issues |
|
|
208
|
+
|---|---|---|
|
|
209
|
+
| VoiceOver | Pass / Fail | |
|
|
210
|
+
| Voice Control | Pass / Fail | |
|
|
211
|
+
| Larger Text | Pass / Fail | |
|
|
212
|
+
| Sufficient Contrast | Pass / Fail | |
|
|
213
|
+
| Dark Interface | Pass / Fail | |
|
|
214
|
+
| Differentiate Without Color | Pass / Fail | |
|
|
215
|
+
| Reduced Motion | Pass / Fail | |
|
|
216
|
+
| Captions | Pass / Fail / N/A | |
|
|
217
|
+
| Audio Descriptions | Pass / Fail / N/A | |
|
|
218
|
+
|
|
219
|
+
### App Store recommendation draft
|
|
220
|
+
|
|
221
|
+
Use the completed summary above to prepare an App Store Accessibility Nutrition Label recommendation:
|
|
222
|
+
|
|
223
|
+
- You could claim: every label marked Pass
|
|
224
|
+
- You should not claim: every label marked Fail
|
|
225
|
+
- Not applicable: every label marked N/A
|
|
226
|
+
- Add short reasons for both supported and unsupported labels
|
|
227
|
+
|
|
228
|
+
Example handoff:
|
|
229
|
+
|
|
230
|
+
```md
|
|
231
|
+
Accessibility Nutrition Label recommendation
|
|
232
|
+
|
|
233
|
+
You could claim:
|
|
234
|
+
- VoiceOver
|
|
235
|
+
- Voice Control
|
|
236
|
+
- Larger Text
|
|
237
|
+
- Sufficient Contrast
|
|
238
|
+
- Dark Interface
|
|
239
|
+
- Differentiate Without Color
|
|
240
|
+
- Reduced Motion
|
|
241
|
+
|
|
242
|
+
Why you could claim them:
|
|
243
|
+
- VoiceOver: all reviewed common tasks are reachable, labeled, and operable with VoiceOver
|
|
244
|
+
- Voice Control: all reviewed interactive elements can be activated by visible name or input label
|
|
245
|
+
- Larger Text: reviewed screens reflow correctly and remain readable at the largest supported sizes
|
|
246
|
+
- Sufficient Contrast: reviewed text and interactive elements meet contrast requirements in light and dark mode
|
|
247
|
+
- Dark Interface: reviewed screens support dark appearance without unreadable content or broken chrome
|
|
248
|
+
- Differentiate Without Color: reviewed states and status indicators remain understandable without color alone
|
|
249
|
+
- Reduced Motion: reviewed transitions and state changes respect Reduce Motion
|
|
250
|
+
|
|
251
|
+
You should not claim:
|
|
252
|
+
- Captions
|
|
253
|
+
- Audio Descriptions
|
|
254
|
+
|
|
255
|
+
Why you should not claim them:
|
|
256
|
+
- Captions: the app has no primary video or long-form media experience in the reviewed scope
|
|
257
|
+
- Audio Descriptions: the app has no video content that would justify this label in the reviewed scope
|
|
258
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Antoine van der Lee
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: swift-concurrency
|
|
3
|
+
description: 'Diagnose data races, convert callback-based code to async/await, implement actor isolation patterns, resolve Sendable conformance issues, and guide Swift 6 migration. Use when developers mention: (1) Swift Concurrency, async/await, actors, or tasks, (2) "use Swift Concurrency" or "modern concurrency patterns", (3) migrating to Swift 6, (4) data races or thread safety issues, (5) refactoring closures to async/await, (6) @MainActor, Sendable, or actor isolation, (7) concurrent code architecture or performance optimization, (8) concurrency-related linter warnings (SwiftLint or similar; e.g. async_without_await, Sendable/actor isolation/MainActor lint).'
|
|
4
|
+
---
|
|
5
|
+
# Swift Concurrency
|
|
6
|
+
|
|
7
|
+
## Fast Path
|
|
8
|
+
|
|
9
|
+
Before proposing a fix:
|
|
10
|
+
|
|
11
|
+
1. Analyze `Package.swift` or `.pbxproj` to determine Swift language mode, strict concurrency level, default isolation, and upcoming features. Do this always, not only for migration work.
|
|
12
|
+
2. Capture the exact diagnostic and offending symbol.
|
|
13
|
+
3. Determine the isolation boundary: `@MainActor`, custom actor, actor instance isolation, or `nonisolated`.
|
|
14
|
+
4. Confirm whether the code is UI-bound or intended to run off the main actor.
|
|
15
|
+
|
|
16
|
+
Project settings that change concurrency behavior:
|
|
17
|
+
|
|
18
|
+
| Setting | SwiftPM (`Package.swift`) | Xcode (`.pbxproj`) |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| Language mode | `swiftLanguageVersions` or `-swift-version` (`// swift-tools-version:` is not a reliable proxy) | Swift Language Version |
|
|
21
|
+
| Strict concurrency | `.enableExperimentalFeature("StrictConcurrency=targeted")` | `SWIFT_STRICT_CONCURRENCY` |
|
|
22
|
+
| Default isolation | `.defaultIsolation(MainActor.self)` | `SWIFT_DEFAULT_ACTOR_ISOLATION` |
|
|
23
|
+
| Upcoming features | `.enableUpcomingFeature("NonisolatedNonsendingByDefault")` | `SWIFT_UPCOMING_FEATURE_*` |
|
|
24
|
+
|
|
25
|
+
If any of these are unknown, ask the developer to confirm them before giving migration-sensitive guidance. Do not guess.
|
|
26
|
+
|
|
27
|
+
Guardrails:
|
|
28
|
+
|
|
29
|
+
- Do not recommend `@MainActor` as a blanket fix. Justify why the code is truly UI-bound.
|
|
30
|
+
- Prefer structured concurrency over unstructured tasks. Use `Task.detached` only with a clear reason.
|
|
31
|
+
- If recommending `@preconcurrency`, `@unchecked Sendable`, or `nonisolated(unsafe)`, require a documented safety invariant and a follow-up removal plan.
|
|
32
|
+
- Optimize for the smallest safe change. Do not refactor unrelated architecture during migration.
|
|
33
|
+
- Course references are for deeper learning only. Use them sparingly and only when they clearly help answer the developer's question.
|
|
34
|
+
|
|
35
|
+
## Quick Fix Mode
|
|
36
|
+
|
|
37
|
+
Use Quick Fix Mode when all of these are true:
|
|
38
|
+
|
|
39
|
+
- The issue is localized to one file or one type.
|
|
40
|
+
- The isolation boundary is clear.
|
|
41
|
+
- The fix can be explained in 1-2 behavior-preserving steps.
|
|
42
|
+
|
|
43
|
+
Skip Quick Fix Mode when any of these are true:
|
|
44
|
+
|
|
45
|
+
- Build settings or default isolation are unknown.
|
|
46
|
+
- The issue crosses module boundaries or changes public API behavior.
|
|
47
|
+
- The likely fix depends on unsafe escape hatches.
|
|
48
|
+
|
|
49
|
+
## Common Diagnostics
|
|
50
|
+
|
|
51
|
+
| Diagnostic | First check | Smallest safe fix | Escalate to |
|
|
52
|
+
|---|---|---|---|
|
|
53
|
+
| `Main actor-isolated ... cannot be used from a nonisolated context` | Is this truly UI-bound? | Isolate the caller to `@MainActor` or use `await MainActor.run { ... }` only when main-actor ownership is correct. | `references/actors.md`, `references/threading.md` |
|
|
54
|
+
| `Actor-isolated type does not conform to protocol` | Must the requirement run on the actor? | Prefer isolated conformance (e.g., `extension Foo: @MainActor SomeProtocol`); use `nonisolated` only for truly nonisolated requirements. | `references/actors.md` |
|
|
55
|
+
| `Sending value of non-Sendable type ... risks causing data races` | What isolation boundary is being crossed? | Keep access inside one actor, or convert the transferred value to an immutable/value type. | `references/sendable.md`, `references/threading.md` |
|
|
56
|
+
| `SwiftLint async_without_await` | Is `async` actually required by protocol, override, or `@concurrent`? | Remove `async`, or use a narrow suppression with rationale. Never add fake awaits. | `references/linting.md` |
|
|
57
|
+
| `wait(...) is unavailable from asynchronous contexts` | Is this legacy XCTest async waiting? | Replace with `await fulfillment(of:)` or Swift Testing equivalents. | `references/testing.md` |
|
|
58
|
+
| Core Data concurrency warnings | Are `NSManagedObject` instances crossing contexts or actors? | Pass `NSManagedObjectID` or map to a Sendable value type. | `references/core-data.md` |
|
|
59
|
+
| `Thread.current` unavailable from asynchronous contexts | Are you debugging by thread instead of isolation? | Reason in terms of isolation and use Instruments/debugger instead. | `references/threading.md` |
|
|
60
|
+
| SwiftLint concurrency-related warnings | Which specific lint rule triggered? | Use `references/linting.md` for rule intent and preferred fixes; avoid dummy awaits. | `references/linting.md` |
|
|
61
|
+
|
|
62
|
+
## When Quick Fixes Fail
|
|
63
|
+
|
|
64
|
+
1. Gather project settings if not already confirmed.
|
|
65
|
+
2. Re-evaluate which isolation boundaries the type crosses.
|
|
66
|
+
3. Route to the matching reference file for a deeper fix.
|
|
67
|
+
4. If the fix may change behavior, document the invariant and add verification steps.
|
|
68
|
+
|
|
69
|
+
## Smallest Safe Fixes
|
|
70
|
+
|
|
71
|
+
Prefer changes that preserve behavior while satisfying data-race safety:
|
|
72
|
+
|
|
73
|
+
- **UI-bound state**: isolate the type or member to `@MainActor`.
|
|
74
|
+
- **Shared mutable state**: move it behind an `actor`, or use `@MainActor` only if the state is UI-owned.
|
|
75
|
+
- **Background work**: when work must hop off caller isolation, use an `async` API marked `@concurrent`; when work can safely inherit caller isolation, use `nonisolated` without `@concurrent`.
|
|
76
|
+
- **Sendability issues**: prefer immutable values and explicit boundaries over `@unchecked Sendable`.
|
|
77
|
+
|
|
78
|
+
## Concurrency Tool Selection
|
|
79
|
+
|
|
80
|
+
| Need | Tool | Key Guidance |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| Single async operation | `async/await` | Default choice for sequential async work |
|
|
83
|
+
| Fixed parallel operations | `async let` | Known count at compile time; auto-cancelled on throw |
|
|
84
|
+
| Dynamic parallel operations | `withTaskGroup` | Unknown count; structured — cancels children on scope exit |
|
|
85
|
+
| Sync → async bridge | `Task { }` | Inherits actor context; use `Task.detached` only with documented reason |
|
|
86
|
+
| Shared mutable state | `actor` | Prefer over locks/queues; keep isolated sections small |
|
|
87
|
+
| UI-bound state | `@MainActor` | Only for truly UI-related code; justify isolation |
|
|
88
|
+
|
|
89
|
+
### Common Scenarios
|
|
90
|
+
|
|
91
|
+
**Network request with UI update**
|
|
92
|
+
```swift
|
|
93
|
+
Task { @concurrent in
|
|
94
|
+
let data = try await fetchData()
|
|
95
|
+
await MainActor.run { self.updateUI(with: data) }
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Processing array items in parallel**
|
|
100
|
+
```swift
|
|
101
|
+
await withTaskGroup(of: ProcessedItem.self) { group in
|
|
102
|
+
for item in items {
|
|
103
|
+
group.addTask { await process(item) }
|
|
104
|
+
}
|
|
105
|
+
for await result in group {
|
|
106
|
+
results.append(result)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Swift 6 Migration Quick Guide
|
|
112
|
+
|
|
113
|
+
Key changes in Swift 6:
|
|
114
|
+
- **Strict concurrency checking** enabled by default
|
|
115
|
+
- **Complete data-race safety** at compile time
|
|
116
|
+
- **Sendable requirements** enforced on boundaries
|
|
117
|
+
- **Isolation checking** for all async boundaries
|
|
118
|
+
|
|
119
|
+
### Migration Validation Loop
|
|
120
|
+
|
|
121
|
+
Apply this cycle for each migration change:
|
|
122
|
+
|
|
123
|
+
1. **Build** — Run `swift build` or Xcode build to surface new diagnostics
|
|
124
|
+
2. **Fix** — Address one category of error at a time (e.g., all Sendable issues first)
|
|
125
|
+
3. **Rebuild** — Confirm the fix compiles cleanly before moving on
|
|
126
|
+
4. **Test** — Run the test suite to catch regressions (`swift test` or Cmd+U)
|
|
127
|
+
5. **Only proceed** to the next file/module when all diagnostics are resolved
|
|
128
|
+
|
|
129
|
+
If a fix introduces new warnings, resolve them before continuing. Never batch multiple unrelated fixes — keep commits small and reviewable.
|
|
130
|
+
|
|
131
|
+
For detailed migration steps, see `references/migration.md`.
|
|
132
|
+
|
|
133
|
+
## Reference Router
|
|
134
|
+
|
|
135
|
+
Open the smallest reference that matches the question:
|
|
136
|
+
|
|
137
|
+
- Foundations
|
|
138
|
+
- `references/async-await-basics.md` — async/await syntax, execution order, async let, URLSession patterns
|
|
139
|
+
- `references/tasks.md` — Task lifecycle, cancellation, priorities, task groups, structured vs unstructured
|
|
140
|
+
- `references/actors.md` — Actor isolation, @MainActor, global actors, reentrancy, custom executors, Mutex
|
|
141
|
+
- `references/sendable.md` — Sendable conformance, value/reference types, @unchecked, region isolation
|
|
142
|
+
- `references/threading.md` — Execution model, suspension points, Swift 6.2 isolation behavior
|
|
143
|
+
- Streams
|
|
144
|
+
- `references/async-sequences.md` — AsyncSequence, AsyncStream, when to use vs regular async methods
|
|
145
|
+
- `references/async-algorithms.md` — Debounce, throttle, merge, combineLatest, channels, timers
|
|
146
|
+
- Applied topics
|
|
147
|
+
- `references/testing.md` — Swift Testing first, XCTest fallback, leak checks
|
|
148
|
+
- `references/performance.md` — Profiling with Instruments, reducing suspension points, execution strategies
|
|
149
|
+
- `references/memory-management.md` — Retain cycles in tasks, memory safety patterns
|
|
150
|
+
- `references/core-data.md` — NSManagedObject sendability, custom executors, isolation conflicts
|
|
151
|
+
- Migration and tooling
|
|
152
|
+
- `references/migration.md` — Swift 6 migration strategy, closure-to-async conversion, @preconcurrency, FRP migration
|
|
153
|
+
- `references/linting.md` — Concurrency-focused lint rules and SwiftLint `async_without_await`
|
|
154
|
+
- Glossary
|
|
155
|
+
- `references/glossary.md` — Quick definitions of core concurrency terms
|
|
156
|
+
|
|
157
|
+
## Verification Checklist
|
|
158
|
+
|
|
159
|
+
When changing concurrency code:
|
|
160
|
+
|
|
161
|
+
1. Re-check build settings before interpreting diagnostics.
|
|
162
|
+
2. Build and clear one category of errors before moving on. Do not batch unrelated fixes into the same change.
|
|
163
|
+
3. Run tests, especially actor-, lifetime-, and cancellation-sensitive tests.
|
|
164
|
+
4. Use Instruments for performance claims instead of guessing.
|
|
165
|
+
5. Verify deallocation and cancellation behavior for long-lived tasks.
|
|
166
|
+
6. Check `Task.isCancelled` in long-running operations.
|
|
167
|
+
7. Never use semaphores or ad hoc locking in async contexts when actor isolation or `Mutex` would express ownership more safely.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
**Note**: This skill is based on the comprehensive [Swift Concurrency Course](https://www.swiftconcurrencycourse.com?utm_source=github&utm_medium=agent-skill&utm_campaign=skill-footer) by Antoine van der Lee.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Reference Index
|
|
2
|
+
|
|
3
|
+
Quick navigation for the Swift Concurrency skill.
|
|
4
|
+
|
|
5
|
+
## Foundations
|
|
6
|
+
|
|
7
|
+
| File | Use it for |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `async-await-basics.md` | closure-to-async bridges and foundational async/await usage |
|
|
10
|
+
| `tasks.md` | `Task`, cancellation, task groups, structured vs unstructured work |
|
|
11
|
+
| `actors.md` | actor isolation, `@MainActor`, reentrancy, isolated conformances |
|
|
12
|
+
| `sendable.md` | `Sendable`, `@Sendable`, region isolation, escape hatches |
|
|
13
|
+
| `threading.md` | execution model, suspension points, Swift 6.2 isolation behavior |
|
|
14
|
+
|
|
15
|
+
## Streams
|
|
16
|
+
|
|
17
|
+
| File | Use it for |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `async-sequences.md` | deciding between `AsyncSequence`, `AsyncStream`, and one-shot async APIs |
|
|
20
|
+
| `async-algorithms.md` | debounce, throttle, merge, `combineLatest`, channels, timers |
|
|
21
|
+
|
|
22
|
+
## Applied Topics
|
|
23
|
+
|
|
24
|
+
| File | Use it for |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `testing.md` | Swift Testing first, XCTest fallback, leak checks |
|
|
27
|
+
| `performance.md` | Instruments workflow, actor hops, suspension cost |
|
|
28
|
+
| `memory-management.md` | retain cycles, long-lived tasks, cleanup |
|
|
29
|
+
| `core-data.md` | `NSManagedObjectID`, `perform`, default isolation conflicts |
|
|
30
|
+
|
|
31
|
+
## Migration and Tooling
|
|
32
|
+
|
|
33
|
+
| File | Use it for |
|
|
34
|
+
|---|---|
|
|
35
|
+
| `migration.md` | rollout order, build settings, migration guardrails |
|
|
36
|
+
| `linting.md` | concurrency-focused lint rules |
|
|
37
|
+
| `glossary.md` | quick definitions |
|
|
38
|
+
|
|
39
|
+
## Problem Router
|
|
40
|
+
|
|
41
|
+
- "I need to fix a compiler error quickly" → `../SKILL.md`
|
|
42
|
+
- "I need to replace a callback with async/await" → `async-await-basics.md`
|
|
43
|
+
- "I need to protect shared mutable state" → `actors.md`
|
|
44
|
+
- "I need to pass data safely across boundaries" → `sendable.md`
|
|
45
|
+
- "I need stream operators" → `async-algorithms.md`
|
|
46
|
+
- "I need to understand why code runs where it runs" → `threading.md`
|
|
47
|
+
- "I need to stop a leak or lifetime issue" → `memory-management.md`
|
|
48
|
+
- "I need to migrate to Swift 6" → `migration.md`
|
|
49
|
+
- "I need to test async code" → `testing.md`
|
|
50
|
+
- "I need to optimize slow async code" → `performance.md`
|