{"id":"77785756-87cc-4978-9a16-f0741c724d01","shortId":"btDbXP","kind":"skill","title":"swiftdata","tagline":"Implement, review, or improve data persistence using SwiftData. Use when defining @Model classes with @Attribute, @Relationship, @Transient, @Unique, or @Index; when querying with @Query, #Predicate, FetchDescriptor, or SortDescriptor; when configuring ModelContainer and ModelCon","description":"# SwiftData\n\nPersist, query, and manage structured data in iOS 26+ apps using SwiftData\nwith Swift 6.3.\n\n## Contents\n\n- [Model Definition](#model-definition)\n- [ModelContainer Setup](#modelcontainer-setup)\n- [CRUD Operations](#crud-operations)\n- [@Query in SwiftUI](#query-in-swiftui)\n- [#Predicate](#predicate)\n- [FetchDescriptor](#fetchdescriptor)\n- [Schema Versioning and Migration](#schema-versioning-and-migration)\n- [Concurrency (@ModelActor)](#concurrency-modelactor)\n- [SwiftUI Integration](#swiftui-integration)\n- [Common Mistakes](#common-mistakes)\n- [Review Checklist](#review-checklist)\n- [References](#references)\n\n## Model Definition\n\nApply `@Model` to a **class** (not struct). Generates `PersistentModel`, `Observable`, `Sendable`.\n\n```swift\n@Model\nclass Trip {\n    var name: String\n    var destination: String\n    var startDate: Date\n    var endDate: Date\n    var isFavorite: Bool = false\n    @Attribute(.externalStorage) var imageData: Data?\n    @Relationship(deleteRule: .cascade, inverse: \\LivingAccommodation.trip)\n    var accommodation: LivingAccommodation?\n    @Transient var isSelected: Bool = false  // Always provide default\n\n    init(name: String, destination: String, startDate: Date, endDate: Date) {\n        self.name = name; self.destination = destination\n        self.startDate = startDate; self.endDate = endDate\n    }\n}\n```\n\n**@Attribute options**: `.externalStorage`, `.unique`, `.spotlight`, `.allowsCloudEncryption`, `.preserveValueOnDeletion` (iOS 18+), `.ephemeral`, `.transformable(by:)`. Rename: `@Attribute(originalName: \"old_name\")`.\n\n**@Relationship**: `deleteRule:` `.cascade`/`.nullify`(default)/`.deny`/`.noAction`. Specify `inverse:` for reliable behavior. Unidirectional (iOS 18+): `inverse: nil`.\n\n**#Unique (iOS 18+)**: `#Unique<Person>([\\.firstName, \\.lastName])` -- compound uniqueness.\n\n**Inheritance (iOS 26+)**: `@Model class BusinessTrip: Trip { var company: String }`.\n\nSupported types: `Bool`, `Int`/`UInt` variants, `Float`, `Double`, `String`, `Date`, `Data`, `URL`, `UUID`, `Decimal`, `Array`, `Dictionary`, `Set`, `Codable` enums, `Codable` structs (composite, iOS 18+), relationships to `@Model` classes.\n\n## ModelContainer Setup\n\n```swift\n// Basic\nlet container = try ModelContainer(for: Trip.self, LivingAccommodation.self)\n\n// Configured\nlet config = ModelConfiguration(\"Store\", isStoredInMemoryOnly: false,\n    groupContainer: .identifier(\"group.com.example.app\"),\n    cloudKitDatabase: .private(\"iCloud.com.example.app\"))\nlet container = try ModelContainer(for: Trip.self, configurations: config)\n\n// With migration plan\nlet container = try ModelContainer(for: SchemaV2.Trip.self,\n    migrationPlan: TripMigrationPlan.self)\n\n// In-memory (previews/tests)\nlet container = try ModelContainer(for: Trip.self,\n    configurations: ModelConfiguration(isStoredInMemoryOnly: true))\n```\n\n## CRUD Operations\n\n```swift\n// CREATE\nlet trip = Trip(name: \"Summer\", destination: \"Paris\", startDate: .now, endDate: .now + 86400*7)\nmodelContext.insert(trip)\ntry modelContext.save()  // or rely on autosave\n\n// READ\nlet trips = try modelContext.fetch(FetchDescriptor<Trip>(\n    predicate: #Predicate { $0.destination == \"Paris\" },\n    sortBy: [SortDescriptor(\\.startDate)]))\n\n// UPDATE -- modify properties directly; autosave handles persistence\ntrip.destination = \"Rome\"\n\n// DELETE\nmodelContext.delete(trip)\ntry modelContext.delete(model: Trip.self, where: #Predicate { $0.isFavorite == false })\n\n// TRANSACTION (atomic)\ntry modelContext.transaction {\n    modelContext.insert(trip); trip.isFavorite = true\n}\n```\n\n## @Query in SwiftUI\n\n```swift\nstruct TripListView: View {\n    @Query(filter: #Predicate<Trip> { $0.isFavorite == true },\n           sort: \\.startDate, order: .reverse)\n    private var favorites: [Trip]\n\n    var body: some View { List(favorites) { trip in Text(trip.name) } }\n}\n\n// Dynamic query via init\nstruct SearchView: View {\n    @Query private var trips: [Trip]\n    init(search: String) {\n        _trips = Query(filter: #Predicate<Trip> { trip in\n            search.isEmpty || trip.name.localizedStandardContains(search)\n        }, sort: [SortDescriptor(\\.name)])\n    }\n    var body: some View { List(trips) { trip in Text(trip.name) } }\n}\n\n// FetchDescriptor query\nstruct RecentView: View {\n    static var desc: FetchDescriptor<Trip> {\n        var d = FetchDescriptor<Trip>(sortBy: [SortDescriptor(\\.startDate)])\n        d.fetchLimit = 5; return d\n    }\n    @Query(RecentView.desc) private var recent: [Trip]\n    var body: some View { List(recent) { trip in Text(trip.name) } }\n}\n```\n\n## #Predicate\n\n```swift\n#Predicate<Trip> { $0.destination.localizedStandardContains(\"paris\") }  // String\n#Predicate<Trip> { $0.startDate > Date.now }                            // Date\n#Predicate<Trip> { $0.isFavorite && $0.destination != \"Unknown\" }       // Compound\n#Predicate<Trip> { $0.accommodation?.name != nil }                      // Optional\n#Predicate<Trip> { $0.tags.contains { $0.name == \"adventure\" } }        // Collection\n```\n\nSupported: `==`, `!=`, `<`, `<=`, `>`, `>=`, `&&`, `||`, `!`, `contains()`, `allSatisfy()`, `filter()`, `starts(with:)`, `localizedStandardContains()`, `caseInsensitiveCompare()`, arithmetic, ternary, optional chaining, nil coalescing, type casting. **Not supported**: flow control, nested declarations, arbitrary method calls.\n\n## FetchDescriptor\n\n```swift\nvar d = FetchDescriptor<Trip>(predicate: ..., sortBy: [...])\nd.fetchLimit = 20; d.fetchOffset = 0\nd.includePendingChanges = true\nd.propertiesToFetch = [\\.name, \\.startDate]\nd.relationshipKeyPathsForPrefetching = [\\.accommodation]\nlet trips = try modelContext.fetch(d)\nlet count = try modelContext.fetchCount(d)\nlet ids = try modelContext.fetchIdentifiers(d)\ntry modelContext.enumerate(d, batchSize: 1000) { trip in trip.isProcessed = true }\n```\n\n## Schema Versioning and Migration\n\n```swift\nenum SchemaV1: VersionedSchema {\n    static var versionIdentifier = Schema.Version(1, 0, 0)\n    static var models: [any PersistentModel.Type] { [Trip.self] }\n    @Model class Trip { var name: String; init(name: String) { self.name = name } }\n}\n\nenum SchemaV2: VersionedSchema {\n    static var versionIdentifier = Schema.Version(2, 0, 0)\n    static var models: [any PersistentModel.Type] { [Trip.self] }\n    @Model class Trip {\n        var name: String; var startDate: Date?  // New property\n        init(name: String) { self.name = name }\n    }\n}\n\nenum TripMigrationPlan: SchemaMigrationPlan {\n    static var schemas: [any VersionedSchema.Type] { [SchemaV1.self, SchemaV2.self] }\n    static var stages: [MigrationStage] { [migrateV1toV2] }\n    static let migrateV1toV2 = MigrationStage.lightweight(\n        fromVersion: SchemaV1.self, toVersion: SchemaV2.self)\n}\n\n// Custom migration for data transformation\nstatic let migrateV2toV3 = MigrationStage.custom(\n    fromVersion: SchemaV2.self, toVersion: SchemaV3.self,\n    willMigrate: nil,\n    didMigrate: { context in\n        let trips = try context.fetch(FetchDescriptor<SchemaV3.Trip>())\n        for trip in trips { trip.displayName = trip.name.capitalized }\n        try context.save()\n    })\n```\n\nLightweight handles: adding optional/defaulted properties, renaming (`originalName`), removing properties, adding model types.\n\n## Concurrency (@ModelActor)\n\n```swift\n@ModelActor\nactor DataHandler {\n    func importTrips(_ records: [TripRecord]) throws {\n        for r in records {\n            modelContext.insert(Trip(name: r.name, destination: r.dest,\n                                    startDate: r.start, endDate: r.end))\n        }\n        try modelContext.save()  // Always save explicitly in @ModelActor\n    }\n\n    func process(tripID: PersistentIdentifier) throws {\n        guard let trip = self[tripID, as: Trip.self] else { return }\n        trip.isProcessed = true; try modelContext.save()\n    }\n}\n\nlet handler = DataHandler(modelContainer: container)\ntry await handler.importTrips(records)\n```\n\n**Rules**: `ModelContainer` is `Sendable`. `ModelContext` is NOT -- use on its creating actor. Pass `PersistentIdentifier` (Sendable) across boundaries. Never pass `@Model` objects across actors.\n\n## SwiftUI Integration\n\n```swift\n@main\nstruct MyApp: App {\n    var body: some Scene {\n        WindowGroup { ContentView() }\n            .modelContainer(for: [Trip.self, LivingAccommodation.self])\n    }\n}\n\nstruct DetailView: View {\n    @Environment(\\.modelContext) private var modelContext\n    let trip: Trip\n    var body: some View {\n        Text(trip.name)\n        Button(\"Delete\") { modelContext.delete(trip) }\n    }\n}\n\n#Preview {\n    let config = ModelConfiguration(isStoredInMemoryOnly: true)\n    let container = try! ModelContainer(for: Trip.self, configurations: config)\n    container.mainContext.insert(Trip(name: \"Preview\", destination: \"London\",\n        startDate: .now, endDate: .now + 86400))\n    return TripListView().modelContainer(container)\n}\n```\n\n## Common Mistakes\n\n**1. @Model on struct** -- Use class. `@Model` requires reference semantics.\n\n**2. @Transient without default** -- Always provide default: `@Transient var x: Bool = false`.\n\n**3. Missing .modelContainer** -- @Query returns empty without a container on the view hierarchy.\n\n**4. Passing model objects across actors:**\n```swift\n// WRONG: await handler.process(trip: trip)\n// CORRECT: await handler.process(tripID: trip.persistentModelID)\n```\n\n**5. ModelContext on wrong actor:**\n```swift\n// WRONG: Task.detached { context.fetch(...) }\n// CORRECT: Use @ModelActor for background work\n```\n\n**6. Unsupported #Predicate expressions:**\n```swift\n// WRONG: #Predicate<Trip> { $0.name.uppercased() == \"PARIS\" }\n// CORRECT: #Predicate<Trip> { $0.name.localizedStandardContains(\"paris\") }\n```\n\n**7. Flow control in #Predicate:**\n```swift\n// WRONG: #Predicate<Trip> { for tag in $0.tags { ... } }\n// CORRECT: #Predicate<Trip> { $0.tags.contains { $0.name == \"x\" } }\n```\n\n**8. No save in @ModelActor** -- Always call `try modelContext.save()` explicitly.\n\n**9. ObservableObject with @Model** -- Never use `ObservableObject`/`@Published`. `@Model` generates `Observable`. Use `@Query` in views.\n\n**10. Non-optional relationship without default:**\n```swift\n// WRONG: var accommodation: LivingAccommodation  // crashes on reconstitution\n// CORRECT: var accommodation: LivingAccommodation?\n```\n\n**11. Cascade without inverse** -- Specify `inverse:` for reliable cascade delete behavior.\n\n**12. DispatchQueue for background data work:**\n```swift\n// WRONG: DispatchQueue.global().async { ModelContext(container).fetch(...) }\n// CORRECT: @ModelActor actor Handler { func fetch() throws { ... } }\n```\n\n## Review Checklist\n\n- [ ] Every `@Model` is a class with a designated initializer\n- [ ] All `@Transient` properties have default values\n- [ ] Relationships specify `deleteRule` and `inverse`\n- [ ] `.modelContainer` attached at scene/root view level\n- [ ] `@Query` used for reactive data display in SwiftUI\n- [ ] `#Predicate` uses only supported operators\n- [ ] Background work uses `@ModelActor`\n- [ ] `PersistentIdentifier` used across actor boundaries\n- [ ] Schema changes have `VersionedSchema` + `SchemaMigrationPlan`\n- [ ] Large data uses `@Attribute(.externalStorage)`\n- [ ] CloudKit models use optionals and avoid unique constraints\n- [ ] Explicit `save()` in `@ModelActor` methods\n- [ ] Previews use `ModelConfiguration(isStoredInMemoryOnly: true)`\n- [ ] `@Model` classes accessed from SwiftUI views are on `@MainActor` via `@ModelActor` or MainActor isolation\n\n## References\n\n- [references/swiftdata-advanced.md](references/swiftdata-advanced.md) — custom data stores, history tracking, CloudKit, composite attributes, model inheritance, undo/redo, performance\n- [references/swiftdata-queries.md](references/swiftdata-queries.md) — @Query variants, FetchDescriptor deep dive, sectioned queries, dynamic queries, background fetch\n- [references/core-data-coexistence.md](references/core-data-coexistence.md) — standalone Core Data patterns and Core Data to SwiftData migration\n- [references/predicate-pitfalls.md](references/predicate-pitfalls.md) — #Predicate runtime crashes, unsupported expressions, safe patterns\n- [references/indexing.md](references/indexing.md) — #Index macro, compound indexes, when to index, migration","tags":["swiftdata","swift","ios","skills","dpearson2699","accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills"],"capabilities":["skill","source-dpearson2699","skill-swiftdata","topic-accessibility","topic-agent-skills","topic-ai-coding","topic-apple","topic-claude-code","topic-codex-skills","topic-cursor-skills","topic-ios","topic-ios-development","topic-liquid-glass","topic-localization","topic-mapkit"],"categories":["swift-ios-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/dpearson2699/swift-ios-skills/swiftdata","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add dpearson2699/swift-ios-skills","source_repo":"https://github.com/dpearson2699/swift-ios-skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 599 github stars · SKILL.md body (12,198 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:53:45.343Z","embedding":null,"createdAt":"2026-04-18T20:33:31.653Z","updatedAt":"2026-05-18T18:53:45.343Z","lastSeenAt":"2026-05-18T18:53:45.343Z","tsv":"'0':545,590,591,617,618 '0.accommodation':501 '0.destination':350,497 '0.destination.localizedstandardcontains':488 '0.isfavorite':373,393,496 '0.name':507,953 '0.name.localizedstandardcontains':936 '0.name.uppercased':932 '0.startdate':492 '0.tags':949 '0.tags.contains':506,952 '1':589,858 '10':980 '1000':572 '11':999 '12':1010 '18':188,211,216,255 '2':616,868 '20':543 '26':44,224 '3':880 '4':893 '5':466,910 '6':925 '6.3':50 '7':333,938 '8':955 '86400':332,851 '9':965 'access':1110 'accommod':153,552,990,997 'across':781,787,897,1077 'actor':711,777,788,898,914,1025,1078 'ad':697,704 'adventur':508 'allowscloudencrypt':185 'allsatisfi':512 'alway':160,734,872,960 'app':45,795 'appli':111 'arbitrari':532 'arithmet':518 'array':246 'async':1019 'atom':376 'attach':1053 'attribut':16,142,180,193,1088,1132 'autosav':341,359 'avoid':1095 'await':763,901,906 'background':923,1013,1071,1148 'basic':263 'batchsiz':571 'behavior':208,1009 'bodi':404,441,476,797,818 'bool':140,158,234,878 'boundari':782,1079 'businesstrip':227 'button':823 'call':534,961 'cascad':149,199,1000,1007 'caseinsensitivecompar':517 'cast':525 'chain':521 'chang':1081 'checklist':103,106,1031 'class':14,115,124,226,259,599,626,863,1036,1109 'cloudkit':1090,1130 'cloudkitdatabas':281 'coalesc':523 'codabl':249,251 'collect':509 'common':97,100,856 'common-mistak':99 'compani':230 'composit':253,1131 'compound':220,499,1175 'concurr':87,90,707 'concurrency-modelactor':89 'config':273,291,829,840 'configur':31,271,290,313,839 'constraint':1097 'contain':265,285,296,308,511,761,834,855,888,1021 'container.maincontext.insert':841 'content':51 'contentview':801 'context':680 'context.fetch':685,918 'context.save':694 'control':529,940 'core':1153,1157 'correct':905,919,934,950,995,1023 'count':559 'crash':992,1166 'creat':320,776 'crud':62,65,317 'crud-oper':64 'custom':664,1125 'd':460,468,538,557,562,567,570 'd.fetchlimit':465,542 'd.fetchoffset':544 'd.includependingchanges':546 'd.propertiestofetch':548 'd.relationshipkeypathsforprefetching':551 'data':6,41,146,242,667,1014,1062,1086,1126,1154,1158 'datahandl':712,759 'date':134,137,169,171,241,494,633 'date.now':493 'decim':245 'declar':531 'deep':1142 'default':162,201,871,874,986,1045 'defin':12 'definit':53,56,110 'delet':364,824,1008 'deleterul':148,198,1049 'deni':202 'desc':457 'design':1039 'destin':130,166,175,326,726,845 'detailview':807 'dictionari':247 'didmigr':679 'direct':358 'dispatchqueu':1011 'dispatchqueue.global':1018 'display':1063 'dive':1143 'doubl':239 'dynam':413,1146 'els':751 'empti':885 'enddat':136,170,179,330,730,849 'enum':250,582,609,641 'environ':809 'ephemer':189 'everi':1032 'explicit':736,964,1098 'express':928,1168 'externalstorag':143,182,1089 'fals':141,159,277,374,879 'favorit':401,408 'fetch':1022,1028,1149 'fetchdescriptor':27,76,77,347,450,458,461,535,539,686,1141 'filter':391,430,513 'firstnam':218 'float':238 'flow':528,939 'fromvers':660,673 'func':713,739,1027 'generat':118,974 'group.com.example.app':280 'groupcontain':278 'guard':744 'handl':360,696 'handler':758,1026 'handler.importtrips':764 'handler.process':902,907 'hierarchi':892 'histori':1128 'icloud.com.example.app':283 'id':564 'identifi':279 'imagedata':145 'implement':2 'importtrip':714 'improv':5 'in-memori':303 'index':21,1173,1176,1179 'inherit':222,1134 'init':163,416,425,604,636 'initi':1040 'int':235 'integr':93,96,790 'invers':150,205,212,1002,1004,1051 'io':43,187,210,215,223,254 'isfavorit':139 'isol':1121 'isselect':157 'isstoredinmemoryon':276,315,831,1106 'larg':1085 'lastnam':219 'let':264,272,284,295,307,321,343,553,558,563,657,670,682,745,757,814,828,833 'level':1057 'lightweight':695 'list':407,444,479 'livingaccommod':154,991,998 'livingaccommodation.self':270,805 'livingaccommodation.trip':151 'localizedstandardcontain':516 'london':846 'macro':1174 'main':792 'mainactor':1116,1120 'manag':39 'memori':305 'method':533,1102 'migrat':81,86,293,580,665,1161,1180 'migratev1tov2':655,658 'migratev2tov3':671 'migrationplan':301 'migrationstag':654 'migrationstage.custom':672 'migrationstage.lightweight':659 'miss':881 'mistak':98,101,857 'model':13,52,55,109,112,123,225,258,369,594,598,621,625,705,785,859,864,895,968,973,1033,1091,1108,1133 'model-definit':54 'modelactor':88,91,708,710,738,921,959,1024,1074,1101,1118 'modelcon':34 'modelconfigur':274,314,830,1105 'modelcontain':32,57,60,260,267,287,298,310,760,767,802,836,854,882,1052 'modelcontainer-setup':59 'modelcontext':770,810,813,911,1020 'modelcontext.delete':365,368,825 'modelcontext.enumerate':569 'modelcontext.fetch':346,556 'modelcontext.fetchcount':561 'modelcontext.fetchidentifiers':566 'modelcontext.insert':334,379,722 'modelcontext.save':337,733,756,963 'modelcontext.transaction':378 'modifi':356 'myapp':794 'name':127,164,173,196,324,439,502,549,602,605,608,629,637,640,724,843 'nest':530 'never':783,969 'new':634 'nil':213,503,522,678 'noaction':203 'non':982 'non-opt':981 'nullifi':200 'object':786,896 'observ':120,975 'observableobject':966,971 'old':195 'oper':63,66,318,1070 'option':181,504,520,983,1093 'optional/defaulted':698 'order':397 'originalnam':194,701 'pari':327,351,489,933,937 'pass':778,784,894 'pattern':1155,1170 'perform':1136 'persist':7,36,361 'persistentidentifi':742,779,1075 'persistentmodel':119 'persistentmodel.type':596,623 'plan':294 'predic':26,74,75,348,349,372,392,431,485,487,491,495,500,505,540,927,931,935,942,945,951,1066,1164 'preservevalueondelet':186 'preview':827,844,1103 'previews/tests':306 'privat':282,399,421,471,811 'process':740 'properti':357,635,699,703,1043 'provid':161,873 'publish':972 'queri':23,25,37,67,71,383,390,414,420,429,451,469,883,977,1058,1139,1145,1147 'query-in-swiftui':70 'r':719 'r.dest':727 'r.end':731 'r.name':725 'r.start':729 'reactiv':1061 'read':342 'recent':473,480 'recentview':453 'recentview.desc':470 'reconstitut':994 'record':715,721,765 'refer':107,108,866,1122 'references/core-data-coexistence.md':1150,1151 'references/indexing.md':1171,1172 'references/predicate-pitfalls.md':1162,1163 'references/swiftdata-advanced.md':1123,1124 'references/swiftdata-queries.md':1137,1138 'relationship':17,147,197,256,984,1047 'reli':339 'reliabl':207,1006 'remov':702 'renam':192,700 'requir':865 'return':467,752,852,884 'revers':398 'review':3,102,105,1030 'review-checklist':104 'rome':363 'rule':766 'runtim':1165 'safe':1169 'save':735,957,1099 'scene':799 'scene/root':1055 'schema':78,83,577,646,1080 'schema-versioning-and-migr':82 'schema.version':588,615 'schemamigrationplan':643,1084 'schemav1':583 'schemav1.self':649,661 'schemav2':610 'schemav2.self':650,663,674 'schemav2.trip.self':300 'schemav3.self':676 'search':426,436 'search.isempty':434 'searchview':418 'section':1144 'self':747 'self.destination':174 'self.enddate':178 'self.name':172,607,639 'self.startdate':176 'semant':867 'sendabl':121,769,780 'set':248 'setup':58,61,261 'skill' 'skill-swiftdata' 'sort':395,437 'sortbi':352,462,541 'sortdescriptor':29,353,438,463 'source-dpearson2699' 'specifi':204,1003,1048 'spotlight':184 'stage':653 'standalon':1152 'start':514 'startdat':133,168,177,328,354,396,464,550,632,728,847 'static':455,585,592,612,619,644,651,656,669 'store':275,1127 'string':128,131,165,167,231,240,427,490,603,606,630,638 'struct':117,252,387,417,452,793,806,861 'structur':40 'summer':325 'support':232,510,527,1069 'swift':49,122,262,319,386,486,536,581,709,791,899,915,929,943,987,1016 'swiftdata':1,9,35,47,1160 'swiftui':69,73,92,95,385,789,1065,1112 'swiftui-integr':94 'tag':947 'task.detached':917 'ternari':519 'text':411,448,483,821 'throw':717,743,1029 'topic-accessibility' 'topic-agent-skills' 'topic-ai-coding' 'topic-apple' 'topic-claude-code' 'topic-codex-skills' 'topic-cursor-skills' 'topic-ios' 'topic-ios-development' 'topic-liquid-glass' 'topic-localization' 'topic-mapkit' 'tovers':662,675 'track':1129 'transact':375 'transform':190,668 'transient':18,155,869,875,1042 'tri':266,286,297,309,336,345,367,377,555,560,565,568,684,693,732,755,762,835,962 'trip':125,228,322,323,335,344,366,380,402,409,423,424,428,432,445,446,474,481,554,573,600,627,683,688,690,723,746,815,816,826,842,903,904 'trip.destination':362 'trip.displayname':691 'trip.isfavorite':381 'trip.isprocessed':575,753 'trip.name':412,449,484,822 'trip.name.capitalized':692 'trip.name.localizedstandardcontains':435 'trip.persistentmodelid':909 'trip.self':269,289,312,370,597,624,750,804,838 'tripid':741,748,908 'triplistview':388,853 'tripmigrationplan':642 'tripmigrationplan.self':302 'triprecord':716 'true':316,382,394,547,576,754,832,1107 'type':233,524,706 'uint':236 'undo/redo':1135 'unidirect':209 'uniqu':19,183,214,217,221,1096 'unknown':498 'unsupport':926,1167 'updat':355 'url':243 'use':8,10,46,773,862,920,970,976,1059,1067,1073,1076,1087,1092,1104 'uuid':244 'valu':1046 'var':126,129,132,135,138,144,152,156,229,400,403,422,440,456,459,472,475,537,586,593,601,613,620,628,631,645,652,796,812,817,876,989,996 'variant':237,1140 'version':79,84,578 'versionedschema':584,611,1083 'versionedschema.type':648 'versionidentifi':587,614 'via':415,1117 'view':389,406,419,443,454,478,808,820,891,979,1056,1113 'willmigr':677 'windowgroup':800 'without':870,886,985,1001 'work':924,1015,1072 'wrong':900,913,916,930,944,988,1017 'x':877,954","prices":[{"id":"111f2a2a-ac77-4125-84f3-ab41c9fc70f8","listingId":"77785756-87cc-4978-9a16-f0741c724d01","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"dpearson2699","category":"swift-ios-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T20:33:31.653Z"}],"sources":[{"listingId":"77785756-87cc-4978-9a16-f0741c724d01","source":"github","sourceId":"dpearson2699/swift-ios-skills/swiftdata","sourceUrl":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/swiftdata","isPrimary":false,"firstSeenAt":"2026-04-18T22:01:22.681Z","lastSeenAt":"2026-05-18T18:53:45.343Z"},{"listingId":"77785756-87cc-4978-9a16-f0741c724d01","source":"skills_sh","sourceId":"dpearson2699/swift-ios-skills/swiftdata","sourceUrl":"https://skills.sh/dpearson2699/swift-ios-skills/swiftdata","isPrimary":true,"firstSeenAt":"2026-04-18T20:33:31.653Z","lastSeenAt":"2026-05-07T22:40:32.316Z"}],"details":{"listingId":"77785756-87cc-4978-9a16-f0741c724d01","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"dpearson2699","slug":"swiftdata","github":{"repo":"dpearson2699/swift-ios-skills","stars":599,"topics":["accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills","ios","ios-development","liquid-glass","localization","mapkit","networking","storekit","swift","swift-concurrency","swiftdata","swiftui","widgetkit","xcode"],"license":"other","html_url":"https://github.com/dpearson2699/swift-ios-skills","pushed_at":"2026-04-26T21:04:17Z","description":"Agent Skills for iOS 26+, Swift 6.3, SwiftUI, and modern Apple frameworks","skill_md_sha":"e0778e02b976f8c8600ed5cff6502652f7fbe4c9","skill_md_path":"skills/swiftdata/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/swiftdata"},"layout":"multi","source":"github","category":"swift-ios-skills","frontmatter":{"name":"swiftdata","description":"Implement, review, or improve data persistence using SwiftData. Use when defining @Model classes with @Attribute, @Relationship, @Transient, @Unique, or @Index; when querying with @Query, #Predicate, FetchDescriptor, or SortDescriptor; when configuring ModelContainer and ModelContext for SwiftUI or background work with @ModelActor; when planning schema migrations with VersionedSchema and SchemaMigrationPlan; when setting up CloudKit sync with ModelConfiguration; or when coexisting with or migrating from Core Data."},"skills_sh_url":"https://skills.sh/dpearson2699/swift-ios-skills/swiftdata"},"updatedAt":"2026-05-18T18:53:45.343Z"}}