Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
ahmed3elshaer avatar

Core Data

  • 22 installs
  • 60 repo stars
  • Updated June 14, 2026
  • ahmed3elshaer/everything-claude-code-mobile

core-data is a Claude Code skill providing iOS persistence patterns for Core Data and SwiftData in SwiftUI apps.

About

core-data is a Claude Code skill with reference patterns for iOS persistence using Core Data and SwiftData. A developer uses it when building the data layer of a SwiftUI app that needs local storage, fetch requests, background writes, or relationships. It also covers migrating from Core Data to SwiftData on iOS 17 and later.

  • Core Data stack setup with view and background contexts
  • Fetch requests, predicates, and relationship modeling examples
  • SwiftData (iOS 17+) models, @Query, and migration guidance

Core Data by the numbers

  • 22 all-time installs (skills.sh)
  • Ranked #711 of 1,039 Mobile Development skills by installs in the Skillselion catalog
  • Data as of Aug 4, 2026 (Skillselion catalog sync)
At a glance

core-data capabilities & compatibility

Capabilities
ios persistence · core data setup · swiftdata migration · fetch requests
Use cases
database
From the docs

What core-data says it does

Core Data for iOS persistence. Data models, fetch requests, background contexts, and SwiftData migration.
SKILL.md
iOS persistence with Core Data and SwiftData.
SKILL.md
npx skills add https://github.com/ahmed3elshaer/everything-claude-code-mobile --skill core-data

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs22
repo stars60
Last updatedJune 14, 2026
Repositoryahmed3elshaer/everything-claude-code-mobile

What it does

Build the local persistence layer of a SwiftUI iOS app with Core Data or SwiftData.

Who is it for?

iOS developers building a Core Data or SwiftData persistence layer in SwiftUI

Skip if: Android or Kotlin Multiplatform persistence

When should I use this skill?

You are building local storage, fetch requests, or background writes in a SwiftUI app

By the numbers

  • Covers both Core Data and SwiftData APIs
  • SwiftData examples target iOS 17+

Files

SKILL.mdMarkdownGitHub ↗

Core Data

iOS persistence with Core Data and SwiftData.

Core Data Stack

Basic Setup

// ✅ Core Data stack
class PersistenceController {
    static let shared = PersistenceController()

    let container: NSPersistentContainer

    init(inMemory: Bool = false) {
        container = NSPersistentContainer(name: "DataModel")

        if inMemory {
            container.persistentStoreDescriptions.first?.url = URL(fileURLWithPath: "/dev/null")
        }

        container.loadPersistentStores { description, error in
            if let error = error {
                fatalError("Core Data store failed to load: \(error)")
            }
        }

        container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
    }

    var viewContext: NSManagedObjectContext {
        container.viewContext
    }

    func backgroundContext() -> NSManagedObjectContext {
        container.newBackgroundContext()
    }
}

SwiftUI Integration

// ✅ @FetchRequest in SwiftUI
struct UserListView: View {
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \User.name, ascending: true)],
        animation: .default)
    private var users: FetchedResults<User>

    var body: some View {
        List {
            ForEach(users) { user in
                Text(user.name ?? "Unknown")
            }
            .onDelete(perform: deleteUsers)
        }
    }

    private func deleteUsers(offsets: IndexSet) {
        withAnimation {
            offsets.map { users[$0] }.forEach(viewContext.delete)

            do {
                try viewContext.save()
            } catch {
                print("Failed to save: \(error)")
            }
        }
    }
}

Fetch Requests

Basic Fetch

// ✅ Simple fetch
func fetchUsers() -> [User] {
    let request: NSFetchRequest<User> = User.fetchRequest()
    request.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]

    do {
        return try viewContext.fetch(request)
    } catch {
        print("Fetch error: \(error)")
        return []
    }
}

// ✅ With predicate
func fetchUsers(named name: String) -> [User] {
    let request: NSFetchRequest<User> = User.fetchRequest()
    request.predicate = NSPredicate(format: "name == %@", name)
    request.fetchLimit = 1

    do {
        return try viewContext.fetch(request)
    } catch {
        return []
    }
}

// ✅ Complex predicate
func searchUsers(query: String) -> [User] {
    let request: NSFetchRequest<User> = User.fetchRequest()
    request.predicate = NSPredicate(
        format: "name CONTAINS[cd] %@ OR email CONTAINS[cd] %@",
        query, query
    )
    request.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]

    do {
        return try viewContext.fetch(request)
    } catch {
        return []
    }
}

Background Context

Background Operations

// ✅ Perform background write
func saveUser(name: String, email: String) {
    let context = PersistenceController.shared.backgroundContext()

    context.perform {
        let user = User(context: context)
        user.name = name
        user.email = email
        user.createdAt = Date()

        do {
            try context.save()
        } catch {
            print("Failed to save: \(error)")
        }
    }
}

// ✅ Batch delete
func deleteAllUsers() {
    let context = PersistenceController.shared.backgroundContext()

    context.perform {
        let fetchRequest: NSFetchRequest<NSFetchRequestResult> = User.fetchRequest()
        let batchDelete = NSBatchDeleteRequest(fetchRequest: fetchRequest)

        do {
            try context.execute(batchDelete)
            try context.save()
        } catch {
            print("Batch delete failed: \(error)")
        }
    }
}

Relationships

Modeling Relationships

// ✅ To-One relationship
extension User {
    @NSManaged var department: Department?
}

// ✅ To-Many relationship
extension Department {
    @NSManaged var employees: NSSet?

    var employeesArray: [User] {
        let set = employees as? Set<User> ?? []
        return set.sorted { $0.name ?? "" < $1.name ?? "" }
    }
}

// ✅ Fetch with relationship
func fetchUsers(in departmentName: String) -> [User] {
    let request: NSFetchRequest<User> = User.fetchRequest()
    request.predicate = NSPredicate(format: "department.name == %@", departmentName)

    do {
        return try viewContext.fetch(request)
    } catch {
        return []
    }
}

SwiftData (iOS 17+)

Basic SwiftData

// ✅ SwiftData model
@Model
final class User {
    var name: String
    var email: String
    var createdAt: Date

    init(name: String, email: String) {
        self.name = name
        self.email = email
        self.createdAt = Date()
    }
}

// ✅ SwiftData setup
@main
struct MyApp: App {
    var sharedModelContainer: ModelContainer = {
        let schema = Schema([User.self])
        let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)

        do {
            return try ModelContainer(for: schema, configurations: [modelConfiguration])
        } catch {
            fatalError("Could not create ModelContainer: \(error)")
        }
    }()

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(sharedModelContainer)
    }
}

// ✅ @Query in SwiftUI
struct UserListView: View {
    @Environment(\.modelContext) private var modelContext
    @Query(sort: \User.name, order: .forward) private var users: [User]

    var body: some View {
        List {
            ForEach(users) { user in
                Text(user.name)
            }
            .onDelete(perform: deleteUsers)
        }
    }

    private func deleteUsers(offsets: IndexSet) {
        withAnimation {
            for index in offsets {
                modelContext.delete(users[index])
            }
        }
    }
}

SwiftData Predicates

// ✅ #Predicate macro
@Query(filter: #Predicate<User> { user in
    user.name.contains("John") && user.createdAt > Date().addingTimeInterval(-86400)
})
var recentJohns: [User]

// ✅ Dynamic predicate
struct UserListView: View {
    @State private var searchText = ""

    var body: some View {
        UserList(searchText: searchText)
    }
}

struct UserList: View {
    let searchText: String

    var predicate: Predicate<User> {
        #Predicate<User> { user in
            user.name.contains(searchText)
        }
    }

    var body: some View {
        @Query(filter: predicate) var users: [User]

        List(users) { user in
            Text(user.name)
        }
    }
}

Migration

Lightweight Migration

let description = NSPersistentStoreDescription(url: storeURL)
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true

Migration Strategy

// ✅ Custom mapping model
func migrateStore(at sourceURL: URL, to destinationURL: URL) {
    let migrationManager = NSMigrationManager(
        sourceStoreAt: sourceURL,
        destinationStoreAt: destinationURL
    )

    do {
        try migrationManager.migrateStore(
            from: sourceURL,
            sourceType: NSSQLiteStoreType,
            with: nil,
            to: destinationURL,
            destinationType: NSSQLiteStoreType
        )
    } catch {
        print("Migration failed: \(error)")
    }
}

Best Practices

// ✅ Use background context for writes
func batchInsert(items: [Item]) {
    let context = backgroundContext()

    context.perform {
        for item in items {
            let managedItem = Item(context: context)
            managedItem.name = item.name
        }

        try? context.save()
    }
}

// ✅ Batch fetch for large datasets
func fetchAllUsersEfficiently() -> [User] {
    let request = NSFetchRequest<User>(entityName: "User")
    request.returnsObjectsAsFaults = false
    request.fetchBatchSize = 100

    return try! viewContext.fetch(request)
}

// ❌ Don't block main thread
// ❌ Bad: Fetching on main thread with large data
let users = viewContext.fetch(largeRequest)  // Blocks UI

// ✅ Good: Background fetch
let context = backgroundContext()
context.perform {
    let users = try! context.fetch(largeRequest)
    DispatchQueue.main.async {
        // Update UI with results
    }
}

---

Remember: Core Data is powerful but complex. Use it for complex data models, consider SwiftData for new projects.

Related skills

FAQ

Does it cover SwiftData?

Yes. It includes SwiftData models with @Model, @Query, and ModelContainer setup for iOS 17 and later.

How does it handle background writes?

It uses a newBackgroundContext() with context.perform for background saves and NSBatchDeleteRequest for batch deletes.

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.