🎯

ios-development

🎯Skill

from travisjneuman/.claude

VibeIndex|
What it does

Develops native Apple platform apps using Swift, SwiftUI, and UIKit, following Apple's design guidelines for iOS, iPadOS, and tvOS.

πŸ“¦

Part of

travisjneuman/.claude(62 items)

ios-development

Installation

git cloneClone repository
git clone https://github.com/travisjneuman/.claude.git ~/.claude
Install ScriptRun install script
curl -fsSL https://raw.githubusercontent.com/travisjneuman/.claude/master/scripts/install.sh | bash
git cloneClone repository
git clone --recurse-submodules https://github.com/travisjneuman/.claude.git ~/.claude
npxRun with npx
npx vite-bundle-visualizer
npxRun with npx
npx knip
Server ConfigurationMCP server configuration block
{ "mcpServers": { // ─────────────────────────────────────────────────────...
πŸ“– Extracted from docs: travisjneuman/.claude
2Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

iOS, iPadOS, and tvOS development with Swift, SwiftUI, and UIKit. Use when building Apple platform apps, implementing iOS-specific features, or following Apple Human Interface Guidelines.

Overview

# iOS/iPadOS/tvOS Development

Comprehensive guide for building native Apple platform applications.

Platforms Covered

| Platform | Minimum Target | Current |

| -------- | -------------- | ----------- |

| iOS | iOS 15.0+ | iOS 17+ |

| iPadOS | iPadOS 15.0+ | iPadOS 17+ |

| tvOS | tvOS 15.0+ | tvOS 17+ |

| watchOS | watchOS 8.0+ | watchOS 10+ |

---

SwiftUI (Preferred for New Projects)

Basic Structure

```swift

import SwiftUI

@main

struct MyApp: App {

var body: some Scene {

WindowGroup {

ContentView()

}

}

}

struct ContentView: View {

@State private var count = 0

var body: some View {

VStack(spacing: 20) {

Text("Count: \(count)")

.font(.largeTitle)

Button("Increment") {

count += 1

}

.buttonStyle(.borderedProminent)

}

.padding()

}

}

```

State Management

```swift

// Local state

@State private var text = ""

// Binding (child components)

@Binding var isPresented: Bool

// Observable object

@StateObject private var viewModel = MyViewModel()

@ObservedObject var viewModel: MyViewModel

// Environment

@Environment(\.dismiss) private var dismiss

@Environment(\.colorScheme) private var colorScheme

@EnvironmentObject var appState: AppState

// App Storage (UserDefaults)

@AppStorage("username") private var username = ""

```

Modern Concurrency

```swift

// Async/await

func fetchData() async throws -> [Item] {

let url = URL(string: "https://api.example.com/items")!

let (data, _) = try await URLSession.shared.data(from: url)

return try JSONDecoder().decode([Item].self, from: data)

}

// In View

.task {

do {

items = try await fetchData()

} catch {

errorMessage = error.localizedDescription

}

}

// Main actor for UI updates

@MainActor

class ViewModel: ObservableObject {

@Published var items: [Item] = []

func load() async {

items = try? await fetchData()

}

}

```

Navigation (iOS 16+)

```swift

// NavigationStack with typed destinations

struct ContentView: View {

@State private var path = NavigationPath()

var body: some View {

NavigationStack(path: $path) {

List(items) { item in

NavigationLink(value: item) {

Text(item.name)

}

}

.navigationDestination(for: Item.self) { item in

DetailView(item: item)

}

}

}

}

```

Lists and Grids

```swift

// Modern List

List {

ForEach(items) { item in

ItemRow(item: item)

}

.onDelete(perform: delete)

.onMove(perform: move)

}

.listStyle(.insetGrouped)

.searchable(text: $searchText)

.refreshable {

await refresh()

}

// LazyVGrid

LazyVGrid(columns: [

GridItem(.adaptive(minimum: 150))

]) {

ForEach(items) { item in

ItemCard(item: item)

}

}

```

---

UIKit (Legacy/Complex UI)

View Controller Lifecycle

```swift

class MyViewController: UIViewController {

override func viewDidLoad() {

super.viewDidLoad()

setupUI()

}

override func viewWillAppear(_ animated: Bool) {

super.viewWillAppear(animated)

// About to appear

}

override func viewDidAppear(_ animated: Bool) {

super.viewDidAppear(animated)

// Fully visible

}

}

```

Auto Layout

```swift

// Programmatic constraints

NSLayoutConstraint.activate([

label.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),

label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),

label.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16)

])

```

---

Data Persistence

Core Data

```swift

// Model

@objc(Item)

public class Item: NSManagedObject {

@NSManaged public var id: UUID

@NSManaged public var name: String

@NSManaged public var createdAt: Date

}

// Fetch

@FetchRequest(

sortDescriptors: [NSSortDescriptor(keyPath: \Item.createdAt, ascending: false)],

animation: .default

)

private var items: FetchedResults

```

SwiftData (iOS 17+)

```swift

@Model

class Item {

var id: UUID

var name: String

var createdAt: Date

init(name: String) {

self.id = UUID()

self.name = name

self.createdAt = Date()

}

}

// In View

@Query(sort: \Item.createdAt, order: .reverse)

private var items: [Item]

@Environment(\.modelContext) private var modelContext

func addItem() {

let item = Item(name: "New Item")

modelContext.insert(item)

}

```

Keychain

```swift

// Store sensitive data

import Security

func saveToKeychain(key: String, data: Data) throws {

let query: [String: Any] = [

kSecClass as String: kSecClassGenericPassword,

kSecAttrAccount as String: key,

kSecValueData as String: data

]

SecItemDelete(query as CFDictionary)

let status = SecItemAdd(query as CFDictionary, nil)

guard status == errSecSuccess else {

throw KeychainError.saveFailed

}

}

```

---

Networking

URLSession

```swift

actor NetworkService {

func fetch(_ type: T.Type, from url: URL) async throws -> T {

let (data, response) = try await URLSession.shared.data(from: url)

guard let httpResponse = response as? HTTPURLResponse,

(200...299).contains(httpResponse.statusCode) else {

throw NetworkError.invalidResponse

}

return try JSONDecoder().decode(T.self, from: data)

}

}

```

---

Apple Human Interface Guidelines

iOS Design Principles

  • Clarity: Text is legible, icons precise, adornments subtle
  • Deference: Content is paramount, UI doesn't compete
  • Depth: Visual layers and realistic motion convey hierarchy

Key Metrics

| Element | Size |

| -------------- | ------------------------------ |

| Touch target | 44x44 pt minimum |

| Navigation bar | 44 pt |

| Tab bar | 49 pt |

| Status bar | 47 pt (notch) / 20 pt (legacy) |

Safe Areas

```swift

.safeAreaInset(edge: .bottom) {

BottomBar()

}

// Ignore safe area

.ignoresSafeArea(.keyboard)

.ignoresSafeArea(.container, edges: .bottom)

```

---

Platform-Specific

iPadOS Specifics

```swift

// Split view

NavigationSplitView {

Sidebar()

} content: {

ContentList()

} detail: {

DetailView()

}

// Keyboard shortcuts

.keyboardShortcut("n", modifiers: .command)

// Hover effects

.hoverEffect(.highlight)

```

tvOS Specifics

```swift

// Focus management

@FocusState private var isFocused: Bool

Button("Action") { }

.focused($isFocused)

.focusable()

// Large text for 10-foot UI

.font(.system(size: 38))

```

---

App Store Requirements

Required Assets

  • App icon (1024x1024)
  • Screenshots for each device size
  • Privacy policy URL
  • App description (4000 char max)

Privacy

```xml

NSCameraUsageDescription

We need camera access to...

NSPhotoLibraryUsageDescription

We need photo access to...

```

App Transport Security

```xml

NSAppTransportSecurity

NSAllowsArbitraryLoads

```

---

Testing

Unit Tests

```swift

import XCTest

@testable import MyApp

final class MyTests: XCTestCase {

func testExample() async throws {

let sut = MyViewModel()

await sut.load()

XCTAssertEqual(sut.items.count, 10)

}

}

```

UI Tests

```swift

import XCTest

final class MyUITests: XCTestCase {

let app = XCUIApplication()

override func setUp() {

continueAfterFailure = false

app.launch()

}

func testNavigation() {

app.buttons["Start"].tap()

XCTAssertTrue(app.staticTexts["Welcome"].exists)

}

}

```

---

Project Structure

```

MyApp/

β”œβ”€β”€ App/

β”‚ └── MyApp.swift

β”œβ”€β”€ Features/

β”‚ β”œβ”€β”€ Home/

β”‚ β”‚ β”œβ”€β”€ HomeView.swift

β”‚ β”‚ └── HomeViewModel.swift

β”‚ └── Settings/

β”‚ └── SettingsView.swift

β”œβ”€β”€ Core/

β”‚ β”œβ”€β”€ Models/

β”‚ β”œβ”€β”€ Services/

β”‚ └── Extensions/

β”œβ”€β”€ Resources/

β”‚ β”œβ”€β”€ Assets.xcassets

β”‚ └── Localizable.strings

└── Tests/

```

---

Best Practices

DO:

  • Use SwiftUI for new projects
  • Support Dynamic Type for accessibility
  • Handle all device orientations
  • Implement proper error handling
  • Use Swift's type system fully

DON'T:

  • Force unwrap optionals without validation
  • Block main thread with network calls
  • Hardcode strings (use localization)
  • Ignore memory management (retain cycles)
  • Skip accessibility labels