Claude-skill-registry ios-reviewer

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/ios-reviewer" ~/.claude/skills/majiayu000-claude-skill-registry-ios-reviewer && rm -rf "$T"
manifest: skills/data/ios-reviewer/SKILL.md
source content

iOS Reviewer Skill

Purpose

Reviews iOS Swift code for SwiftUI, UIKit, Combine, and Swift Concurrency best practices.

When to Use

  • iOS Swift project code review
  • "SwiftUI", "UIKit", "Combine", "async/await" mentions
  • iOS performance, memory management inspection
  • Projects with
    .xcodeproj
    or
    .xcworkspace

Project Detection

  • .xcodeproj
    or
    .xcworkspace
    exists
  • Package.swift
    with iOS platform
  • Info.plist
    exists
  • *.swift
    files present

Workflow

Step 1: Analyze Project

**Swift**: 5.9+
**iOS Target**: 15.0+
**UI Framework**: SwiftUI / UIKit
**Architecture**: MVVM / TCA / Clean Architecture
**Package Manager**: SPM / CocoaPods / Carthage

Step 2: Select Review Areas

AskUserQuestion:

"Which areas to review?"
Options:
- Full iOS pattern check (recommended)
- SwiftUI view patterns
- UIKit lifecycle/memory
- Combine/async-await usage
- Architecture patterns
multiSelect: true

Detection Rules

SwiftUI Patterns

CheckRecommendationSeverity
Heavy computation in bodyMove to ViewModel or task modifierHIGH
Missing @State/@StateObject distinctionUse @StateObject for owned objectsHIGH
ObservableObject without @PublishedAdd @Published to observed propertiesHIGH
Missing EnvironmentObject injectionEnsure parent provides objectMEDIUM
Large View bodyExtract to smaller ViewsMEDIUM
// BAD: Heavy computation in body
struct MyView: View {
    var body: some View {
        let result = expensiveCalculation()  // Called every render
        Text(result)
    }
}

// GOOD: Move to ViewModel or use task
struct MyView: View {
    @StateObject var viewModel = MyViewModel()
    var body: some View {
        Text(viewModel.result)
            .task { await viewModel.calculate() }
    }
}

// BAD: @State for reference type
struct MyView: View {
    @State var viewModel = MyViewModel()  // Won't observe changes
}

// GOOD: @StateObject for reference type
struct MyView: View {
    @StateObject var viewModel = MyViewModel()
}

// BAD: Missing @Published
class MyViewModel: ObservableObject {
    var data: [String] = []  // Changes won't trigger view update
}

// GOOD: Add @Published
class MyViewModel: ObservableObject {
    @Published var data: [String] = []
}

UIKit Patterns

CheckIssueSeverity
Strong delegate referenceRetain cycle riskCRITICAL
Missing removeObserverMemory leakHIGH
Force unwrap IBOutletCrash riskHIGH
viewDidLoad network callUX issueMEDIUM
Main thread UI update missingUndefined behaviorCRITICAL
// BAD: Strong delegate
class MyViewController: UIViewController {
    var delegate: MyDelegate?  // Strong reference!
}

// GOOD: Weak delegate
class MyViewController: UIViewController {
    weak var delegate: MyDelegate?
}

// BAD: Missing removeObserver
override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, ...)
}

// GOOD: Remove in deinit
deinit {
    NotificationCenter.default.removeObserver(self)
}

// BAD: Force unwrap IBOutlet
@IBOutlet var titleLabel: UILabel!
func setup() {
    titleLabel.text = "Hello"  // Crash if not connected
}

// GOOD: Safe unwrap
@IBOutlet weak var titleLabel: UILabel?
func setup() {
    titleLabel?.text = "Hello"
}

Combine Patterns

CheckRecommendationSeverity
Missing store in cancellablesSubscription lostCRITICAL
receive(on:) missing for UIThreading issueHIGH
PassthroughSubject without type erasureExposes implementationMEDIUM
Chain without error handlingSilent failuresMEDIUM
// BAD: Missing store
class MyViewModel {
    func subscribe() {
        publisher.sink { value in
            print(value)
        }  // Immediately cancelled!
    }
}

// GOOD: Store in cancellables
class MyViewModel {
    private var cancellables = Set<AnyCancellable>()

    func subscribe() {
        publisher
            .sink { value in print(value) }
            .store(in: &cancellables)
    }
}

// BAD: Missing receive(on:) for UI
publisher
    .sink { self.label.text = $0 }  // May not be on main thread
    .store(in: &cancellables)

// GOOD: Explicit main thread
publisher
    .receive(on: DispatchQueue.main)
    .sink { self.label.text = $0 }
    .store(in: &cancellables)

Swift Concurrency (async/await)

CheckRecommendationSeverity
Blocking call in async contextUse async alternativeHIGH
Missing @MainActor for UIThreading issueHIGH
Task without cancellation handlingResource leakMEDIUM
Unstructured Task in SwiftUIUse .task modifierMEDIUM
// BAD: Blocking in async
func fetchData() async -> Data {
    return URLSession.shared.dataTask(...)  // Blocking!
}

// GOOD: Async alternative
func fetchData() async throws -> Data {
    let (data, _) = try await URLSession.shared.data(from: url)
    return data
}

// BAD: Missing @MainActor for UI
class MyViewModel: ObservableObject {
    @Published var items: [Item] = []

    func load() async {
        items = await fetchItems()  // May not be on main thread!
    }
}

// GOOD: @MainActor
@MainActor
class MyViewModel: ObservableObject {
    @Published var items: [Item] = []

    func load() async {
        items = await fetchItems()  // Guaranteed main thread
    }
}

// BAD: Unstructured Task in SwiftUI
struct MyView: View {
    var body: some View {
        Text("Hello")
            .onAppear {
                Task { await load() }  // Not cancelled on disappear
            }
    }
}

// GOOD: Use .task modifier
struct MyView: View {
    var body: some View {
        Text("Hello")
            .task { await load() }  // Auto-cancelled
    }
}

Memory Management

CheckProblemSolution
Strong self in closureRetain cycle[weak self] or [unowned self]
Circular referenceMemory leakBreak cycle with weak
Large image in memoryOOM riskUse thumbnails, purge cache
Uncancelled TaskResource leakStore and cancel
// BAD: Strong self in closure
class MyViewController: UIViewController {
    func setup() {
        service.fetch { result in
            self.update(result)  // Strong capture!
        }
    }
}

// GOOD: Weak self
class MyViewController: UIViewController {
    func setup() {
        service.fetch { [weak self] result in
            self?.update(result)
        }
    }
}

Response Template

## iOS Code Review Results

**Project**: [name]
**Swift**: 5.9 | **iOS Target**: 15.0+
**UI Framework**: SwiftUI/UIKit
**Files Analyzed**: X

### SwiftUI Patterns
| Status | File | Issue |
|--------|------|-------|
| HIGH | Views/HomeView.swift | Heavy computation in body (line 45) |
| MEDIUM | Views/ProfileView.swift | Large view body, extract components |

### UIKit/Memory
| Status | File | Issue |
|--------|------|-------|
| CRITICAL | Controllers/DetailVC.swift | Strong delegate reference (line 23) |
| HIGH | Controllers/ListVC.swift | Missing removeObserver in deinit |

### Combine/Async
| Status | File | Issue |
|--------|------|-------|
| CRITICAL | Services/DataService.swift | Missing cancellable store |
| HIGH | ViewModels/MainVM.swift | Missing @MainActor |

### Recommended Actions
1. [ ] Add [weak self] to closures
2. [ ] Use @StateObject for owned ObservableObjects
3. [ ] Add @MainActor to ViewModels
4. [ ] Replace Task with .task modifier

Best Practices

  1. SwiftUI: Prefer small, composable Views with proper state ownership
  2. UIKit: Always use weak delegates, clean up observers
  3. Combine: Store subscriptions, handle threading explicitly
  4. Concurrency: Use structured concurrency, @MainActor for UI
  5. Memory: Use weak captures, profile with Instruments

Integration

  • code-reviewer
    skill: General Swift code quality
  • test-generator
    skill: iOS XCTest generation
  • security-scanner
    skill: iOS security checks

Notes

  • Based on Swift 5.9+, iOS 15+
  • Supports SwiftUI and UIKit projects
  • Includes Swift Concurrency patterns (async/await)