ARC Labs Studio - Code Quality Standards
Instructions
Zero Warnings Policy
Warnings = errors. Never compile or commit code with warnings.
| Warning type | Fix |
|---|---|
| Unused variable | Rename to _ |
| Unused result | Assign to _ = |
| Non-Sendable closure capture | Make type Sendable |
| Any other compiler warning | Fix root cause — no @unchecked Sendable workarounds |
Code Review Checklist (AI-Generated Code)
Forbidden / Deprecated APIs → Modern Equivalents
// foregroundColor() -> foregroundStyle()
Text("Hello").foregroundStyle(.blue)
// cornerRadius() -> clipShape()
Rectangle().clipShape(.rect(cornerRadius: 12))
// NavigationView -> NavigationStack
NavigationStack { ContentView() }
// ObservableObject -> @Observable
@Observable final class ViewModel { }
// DispatchQueue.main.async -> @MainActor async/await
@MainActor func loadData() async { }
// Task.sleep(nanoseconds:) -> Task.sleep(for:)
try await Task.sleep(for: .seconds(1))
// DateFormatter -> .formatted()
let s = date.formatted(.dateTime.year().month().day())
// withAnimation() -> arcWithAnimation() [ARC Labs apps]
arcWithAnimation { state = .loaded }
// NotificationCenter.addObserver(selector:) -> .onReceive
.onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)) { _ in
refresh()
}
// Completion handlers -> async/await
func fetchUser() async throws -> User { ... }
// NEVER: nonisolated(unsafe) — use proper actor isolation
Accessibility Requirements
// onTapGesture -> Button (for VoiceOver)
Button { action() } label: {
Image(systemName: "star")
}
// All buttons need text labels
Button("Add Item", systemImage: "plus") { addItem() }
// Fixed font sizes -> Dynamic Type
Text("Hello").font(.title2) // Not .system(size: 24)
SwiftLint Critical Rules
# Custom rules (errors)
no_force_cast:
regex: 'as!'
severity: error
no_force_try:
regex: 'try!'
severity: error
no_print:
regex: '\bprint\('
message: "Use ARCLogger instead of print()"
severity: warning
# Metrics
line_length: 120 (warning) / 150 (error)
file_length: 400 (warning) / 500 (error)
function_body_length: 40 (warning) / 60 (error)
SwiftFormat Key Settings
--indent 4
--maxwidth 120
--allman false
--self remove
--type-attributes same-line
--func-attributes same-line
--wraparguments after-first
--wrapparameters after-first
--wrapcollections after-first
--closingparen balanced
Multiline Declarations (after-first)
First parameter on the same line as the opening parenthesis:
// Correct: first param on first line, aligned
let viewModel = UserViewModel(getUserUseCase: useCase,
router: router,
analytics: analytics)
// Wrong: first param on new line
// let viewModel = UserViewModel(
// getUserUseCase: useCase,
// router: router
// )
Private Extension Pattern
ALL private methods MUST be in a private extension, never inside the type body:
// Correct
final class MyClass {
// MARK: Public Functions
func doWork() { helper() }
}
// MARK: - Private Functions
private extension MyClass {
func helper() { }
}
Naming Conventions
// Types: PascalCase
struct UserProfile { }
enum LoadingState { }
protocol DataSourceProtocol { }
// Variables/Constants: camelCase
let userName = "John"
var isLoading = false
// Booleans: is/has/should prefix
var isLoading: Bool
var hasPermission: Bool
var shouldRetry: Bool
// Functions: camelCase with descriptive verbs
func loadUser() { }
func validateEmail(_ email: String) -> Bool { }
File Structure
//
// FileName.swift
// ProjectName
//
// Created by ARC Labs Studio on DD/MM/YYYY.
//
import Foundation
import SwiftUI
// Third-party imports
import ARCLogger
import ARCNavigation
struct UserProfile {
// MARK: Private Properties
private(set) var email: String
// MARK: Public Properties
let id: UUID
let name: String
// MARK: Initialization
init(id: UUID, name: String, email: String) { }
// MARK: Public Functions
func validate() -> Bool { }
}
// MARK: - Private Functions
private extension UserProfile {
func formatEmail() -> String { }
}
// MARK: - Identifiable
extension UserProfile: Identifiable { }
DocC Documentation
/// Fetches a user profile from the repository.
///
/// This method first checks the local cache before making a network request.
///
/// - Parameter id: The unique identifier of the user
/// - Returns: The user profile
/// - Throws: `RepositoryError` if the user cannot be fetched
///
/// ## Example
///
/// ```swift
/// let user = try await repository.fetchUser(by: userId)
/// ```
public func fetchUser(by id: UUID) async throws -> User { }
UI Guidelines (Apple HIG)
// Semantic colors (adapt to dark mode)
Color.primary // Text color
Color.secondary // Secondary text
Color.accentColor // Tint color
Color(.systemBackground)
// Dynamic Type
.font(.body) // Scales with user settings
.font(.title)
// Safe area respect
.safeAreaInset(edge: .bottom) { }
.ignoresSafeArea(.keyboard)
// Accessibility
.accessibilityLabel("Add new item")
.accessibilityHint("Double tap to add")
Localization
// All user-facing text must use String(localized:)
Text(String(localized: "welcome_message"))
// Never hardcode strings
// Text("Welcome!") // BAD
References
For complete guidelines:
- @references/code-review.md - AI-generated code review checklist
- @references/code-style.md - SwiftLint/SwiftFormat configuration
- @references/documentation.md - DocC documentation standards
- @references/readme-standards.md - README template
- @references/package-structure.md - Package folder organization
- @references/ui-guidelines.md - HIG, accessibility, dark mode
- @references/api-keys.md - Client secrets & API keys: real-secret vs client-public decision tree, xcconfig → Info.plist →
ConfigurationValue, optional obfuscation
Common Mistakes
- Force unwrapping in production code
- Using
print()instead of ARCLogger - Magic numbers without named constants
- Massive files (>500 lines) or functions (>60 lines)
- Missing access control on public APIs
- Stringly-typed code (use enums/structs)
- Fixed font sizes (breaks Dynamic Type)
- Using
onTapGesturefor interactive elements - Deprecated SwiftUI APIs
Pre-commit Commands
# Format code
swiftformat .
# Lint code
swiftlint
# Fix auto-fixable issues
swiftlint --fix
# Check without modifying
swiftformat --lint .
Examples
Reviewing AI-generated SwiftUI code
User says: "Review this View for quality issues"
- Check for deprecated APIs (foregroundColor, cornerRadius, NavigationView)
- Verify accessibility (Button vs onTapGesture, Dynamic Type, labels)
- Check private extension pattern (no private methods inside type body)
- Verify multiline style (after-first parameter alignment)
- Result: List of issues with specific line references and fixes
Setting up SwiftLint for a new project
User says: "Configure SwiftLint for my package"
- Install:
brew install swiftlint - Copy
.swiftlint.ymlfrom ARCDevTools - Add custom rules (no_force_cast, no_force_try, no_print)
- Set up pre-commit hook
- Result: Automated quality checks on every commit
Related Skills
| If you need... | Use |
|---|---|
| Architecture decisions | /arc-swift-architecture |
| Writing tests | /arc-tdd-patterns |
| Git commits/PRs | /arc-workflow |
| Project setup/ARCDevTools | /arc-project-setup |