# Ios Data Model

> Design SwiftData schema from PRD specification or app analysis. Generates @Model classes with relationships, indexes, migrations, CloudKit sync preparation, and test fixtures. Uses context7 for current SwiftData docs.

- **Type:** Skill
- **Install:** `agentstack add skill-jakeintech-claude-ios-skills-ios-data-model`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Jakeintech](https://agentstack.voostack.com/s/jakeintech)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [Jakeintech](https://github.com/Jakeintech)
- **Source:** https://github.com/Jakeintech/claude-ios-skills/tree/main/skills/ios-data-model

## Install

```sh
agentstack add skill-jakeintech-claude-ios-skills-ios-data-model
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# iOS Data Model — SwiftData Schema Design

Design and implement a complete SwiftData schema from a PRD specification or by analyzing existing app code.

## Process

### Step 1: Read Specification

Read the data model specification from one of:
- `docs/product-vision/data-model-spec.md` (if generated by ios-prd)
- `CLAUDE.md` and brand book for app context (if no PRD)
- `$ARGUMENTS` if user provided inline description

### Step 2: Fetch Current SwiftData Docs

Before designing any schema, use context7 MCP to fetch current SwiftData documentation:
1. Use `resolve-library-id` to find "SwiftData apple developer"
2. Query for `@Model`, `@Relationship`, `@Attribute` patterns
3. Query for `ModelContainer` configuration patterns
4. Query for `#Predicate` and `FetchDescriptor` usage
5. Check for any deprecations in the current SDK version

Load the local reference as well: `${CLAUDE_SKILL_DIR}/swiftdata.md`

### Step 3: Design @Model Classes

For each entity identified in the spec:

```swift
@Model
final class EntityName {
    // Natural key (if applicable)
    @Attribute(.unique) var id: UUID
    
    // Properties with explicit types
    var propertyName: PropertyType
    var createdAt: Date
    
    // Relationships with appropriate delete rules
    @Relationship(deleteRule: .cascade) var children: [ChildEntity]
    @Relationship(deleteRule: .nullify) var parent: ParentEntity?
    
    // Computed/cached properties that don't persist
    @Transient var computedValue: ComputedType = defaultValue
    
    init(id: UUID = UUID(), ...) { }
}
```

For each entity, determine:
- **Natural key:** use `@Attribute(.unique)` for business-level uniqueness
- **Relationships:** cascade deletes where children can't exist without parent; nullify for optional associations
- **Indexes:** add `@Attribute(.index)` for properties used in common predicates
- **Transient:** mark computed/cached properties that should not persist

### Step 4: Design ModelContainer Configuration

```swift
// App Group shared container (required for widget data access)
let schema = Schema([
    EntityOne.self,
    EntityTwo.self,
])

let config = ModelConfiguration(
    schema: schema,
    url: FileManager.default
        .containerURL(forSecurityApplicationGroupIdentifier: "group.com.yourapp.shared")!
        .appendingPathComponent("model.sqlite"),
    cloudKitDatabase: .automatic // or .none if no sync
)

let container = try ModelContainer(for: schema, configurations: [config])
```

Determine:
- **Store location:** App Group container if widgets need data access; default container otherwise
- **CloudKit sync:** `.automatic` for cross-device sync; `.none` for local-only
- **Schema versioning:** wrap in `VersionedSchema` from the start

### Step 5: Design Migration Strategy

```swift
enum AppSchemaV1: VersionedSchema {
    static var versionIdentifier = Schema.Version(1, 0, 0)
    static var models: [any PersistentModel.Type] { [EntityOne.self] }
    
    @Model final class EntityOne {
        // v1 shape
    }
}

enum AppSchemaV2: VersionedSchema {
    static var versionIdentifier = Schema.Version(2, 0, 0)
    static var models: [any PersistentModel.Type] { [EntityOne.self] }
    
    @Model final class EntityOne {
        // v2 shape — added properties
    }
}

enum AppMigrationPlan: SchemaMigrationPlan {
    static var schemas: [any VersionedSchema.Type] { [AppSchemaV1.self, AppSchemaV2.self] }
    static var stages: [MigrationStage] {
        [migrateV1toV2]
    }
    
    static let migrateV1toV2 = MigrationStage.lightweight(
        fromVersion: AppSchemaV1.self,
        toVersion: AppSchemaV2.self
    )
}
```

Rules:
- Additive changes (new optional properties) → lightweight migration
- Renamed properties or changed types → custom migration stage
- Always bump the version even for lightweight migrations

### Step 6: Generate Query Patterns

For each major view/screen, design the `FetchDescriptor`:

```swift
// Example: fetch recent items for home screen
var descriptor = FetchDescriptor(
    predicate: #Predicate { $0.createdAt > cutoffDate },
    sortBy: [SortDescriptor(\.createdAt, order: .reverse)]
)
descriptor.fetchLimit = 50
descriptor.prefetchRelationships = [\.relatedItems]
```

Flag expensive queries: large datasets, complex predicates, or nested relationship traversal.

### Step 7: Generate Test Fixtures

Create `{AppName}Tests/Fixtures/ModelFixtures.swift` with realistic sample data:

```swift
@MainActor
enum ModelFixtures {
    static func makeContainer() throws -> ModelContainer {
        let config = ModelConfiguration(isStoredInMemoryOnly: true)
        return try ModelContainer(for: EntityOne.self, configurations: [config])
    }
    
    static func populateSampleData(context: ModelContext) {
        let item = EntityOne(id: UUID(), name: "Sample Item")
        context.insert(item)
    }
}
```

### Step 8: Follow TDD Order

Write tests before implementation:
1. Write model tests using in-memory `ModelContainer`
2. Test relationship cascade behavior
3. Test unique constraint enforcement
4. Test predicate correctness
5. Then write the `@Model` implementations to make tests pass
6. Use `/ios-tdd` for the full TDD workflow

### Step 9: Commit

Stage and commit all model files:
```bash
git add Shared/Models/ {AppName}Tests/Fixtures/
git commit -m "feat(data-model): add SwiftData schema — {entity list}"
```

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Jakeintech](https://github.com/Jakeintech)
- **Source:** [Jakeintech/claude-ios-skills](https://github.com/Jakeintech/claude-ios-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-jakeintech-claude-ios-skills-ios-data-model
- Seller: https://agentstack.voostack.com/s/jakeintech
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
