Fix Patterns
Fix Patterns
Section titled “Fix Patterns”Concrete before/after examples for each fix category. Reference this when applying approved changes to ensure consistency.
Build Settings Fixes
Section titled “Build Settings Fixes”Debug Information Format (Debug)
Section titled “Debug Information Format (Debug)”Before (project.pbxproj):
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";After:
DEBUG_INFORMATION_FORMAT = dwarf;Compilation Mode (Debug)
Section titled “Compilation Mode (Debug)”Before:
SWIFT_COMPILATION_MODE = wholemodule;After:
SWIFT_COMPILATION_MODE = singlefile;Enable Compilation Caching
Section titled “Enable Compilation Caching”Before (setting absent or):
COMPILATION_CACHE_ENABLE_CACHING = NO;After:
COMPILATION_CACHE_ENABLE_CACHING = YES;Enable Eager Linking (Debug)
Section titled “Enable Eager Linking (Debug)”Before (setting absent):
After:
EAGER_LINKING = YES;Script Phase Fixes
Section titled “Script Phase Fixes”Add Configuration Guard
Section titled “Add Configuration Guard”Before:
# Upload dSYMs to crash reporter./scripts/upload-dsyms.shAfter:
# Upload dSYMs to crash reporter[[ "$CONFIGURATION" != "Release" ]] && exit 0./scripts/upload-dsyms.shAdd Input/Output Declarations
Section titled “Add Input/Output Declarations”When a script has no declared inputs or outputs, Xcode runs it on every build. Declare them in the build phase or use .xcfilelist files for long lists.
Before (in Xcode build phase):
Input Files: (none)Output Files: (none)After:
Input Files: $(SRCROOT)/scripts/generate-constants.sh $(SRCROOT)/Config/constants.json
Output Files: $(DERIVED_FILE_DIR)/GeneratedConstants.swiftSource-Level Fixes
Section titled “Source-Level Fixes”Add Explicit Type Annotations
Section titled “Add Explicit Type Annotations”Before:
let result = items.map { $0.value }.filter { $0 > threshold }.reduce(0, +)After:
let mapped: [Double] = items.map { $0.value }let filtered: [Double] = mapped.filter { $0 > threshold }let result: Double = filtered.reduce(0, +)Break Complex Expressions
Section titled “Break Complex Expressions”Before:
let config = try JSONDecoder().decode( AppConfig.self, from: Data(contentsOf: Bundle.main.url(forResource: "config", withExtension: "json")!))After:
let configURL: URL = Bundle.main.url(forResource: "config", withExtension: "json")!let configData: Data = try Data(contentsOf: configURL)let config: AppConfig = try JSONDecoder().decode(AppConfig.self, from: configData)Mark Classes Final
Section titled “Mark Classes Final”Before:
class NetworkService { func fetchData() async throws -> Data { ... }}After:
final class NetworkService { func fetchData() async throws -> Data { ... }}Only apply when the class is not subclassed anywhere in the project. Search for : NetworkService and class ... : NetworkService before marking final.
Tighten Access Control
Section titled “Tighten Access Control”Before:
class ViewModel { var internalState: State = .idle func processQueue() { ... }}After:
class ViewModel { private var internalState: State = .idle private func processQueue() { ... }}Apply private when the symbol is only used within the same declaration. Apply fileprivate when used within the same file but outside the declaration.
Extract SwiftUI Subviews
Section titled “Extract SwiftUI Subviews”Before:
struct ContentView: View { var body: some View { VStack { HStack { Image(systemName: "person") Text(user.name) Spacer() Button("Edit") { showEdit = true } } List(items) { item in HStack { Text(item.title) Spacer() Text(item.subtitle) .foregroundStyle(.secondary) } } } }}After:
struct ContentView: View { var body: some View { VStack { UserHeaderView(user: user, showEdit: $showEdit) ItemListView(items: items) } }}
struct UserHeaderView: View { let user: User @Binding var showEdit: Bool
var body: some View { HStack { Image(systemName: "person") Text(user.name) Spacer() Button("Edit") { showEdit = true } } }}
struct ItemListView: View { let items: [Item]
var body: some View { List(items) { item in ItemRowView(item: item) } }}
struct ItemRowView: View { let item: Item
var body: some View { HStack { Text(item.title) Spacer() Text(item.subtitle) .foregroundStyle(.secondary) } }}Add Explicit Closure Return Types
Section titled “Add Explicit Closure Return Types”Before:
let handler = { value in guard let result = try? process(value) else { return nil } return result.transformed()}After:
let handler: (InputType) -> OutputType? = { (value: InputType) -> OutputType? in guard let result = try? process(value) else { return nil } return result.transformed()}SPM Restructuring Fixes
Section titled “SPM Restructuring Fixes”Extract Shared Types to Lower-Layer Module
Section titled “Extract Shared Types to Lower-Layer Module”Before (Package.swift):
.target(name: "FeatureA", dependencies: ["FeatureB"]),.target(name: "FeatureB", dependencies: ["FeatureA"]),After:
.target(name: "SharedContracts", dependencies: []),.target(name: "FeatureA", dependencies: ["SharedContracts"]),.target(name: "FeatureB", dependencies: ["SharedContracts"]),Move the shared protocols and types into SharedContracts so both features depend downward instead of on each other.
Extract Interface Module
Section titled “Extract Interface Module”Before:
.target(name: "Networking", dependencies: ["Models"]),.target(name: "FeatureA", dependencies: ["Networking"]),.target(name: "FeatureB", dependencies: ["Networking"]),After:
.target(name: "NetworkingInterface", dependencies: []),.target(name: "Networking", dependencies: ["NetworkingInterface", "Models"]),.target(name: "FeatureA", dependencies: ["NetworkingInterface"]),.target(name: "FeatureB", dependencies: ["NetworkingInterface"]),Feature modules compile against the lightweight interface without waiting for the full implementation to build.