Specialized skill for iOS local data persistence solutions
Implements iOS local data storage using Core Data and Realm.
npx claudepluginhub a5c-ai/babysitterThis skill inherits all available tools. When active, it can use any tool Claude has access to.
README.mdThis skill provides specialized capabilities for iOS local data persistence solutions including Core Data and Realm. It enables designing data models, implementing migrations, configuring iCloud sync, and optimizing database performance.
bash - Execute xcodebuild and swift commandsread - Analyze Core Data models and Realm schemaswrite - Generate model classes and configurationsedit - Update existing persistence codeglob - Search for model files and configurationsgrep - Search for patterns in persistence codeModel Design
CRUD Operations
Migrations
CloudKit Integration
Performance Optimization
Schema Definition
Queries and Filtering
Migrations
Sync Configuration
This skill integrates with the following processes:
ios-core-data-implementation.js - Core Data setup and usageoffline-first-architecture.js - Offline data strategiesmobile-security-implementation.js - Secure data storage// Persistence/PersistenceController.swift
import CoreData
import CloudKit
final class PersistenceController {
static let shared = PersistenceController()
let container: NSPersistentCloudKitContainer
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "MyApp")
if inMemory {
container.persistentStoreDescriptions.first?.url = URL(fileURLWithPath: "/dev/null")
}
// Configure CloudKit
guard let description = container.persistentStoreDescriptions.first else {
fatalError("Failed to retrieve persistent store description")
}
description.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions(
containerIdentifier: "iCloud.com.example.myapp"
)
description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
container.loadPersistentStores { description, error in
if let error = error {
fatalError("Unable to load persistent stores: \(error)")
}
}
container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
}
// MARK: - Preview Support
static var preview: PersistenceController = {
let controller = PersistenceController(inMemory: true)
// Add sample data
return controller
}()
}
// Persistence/RealmManager.swift
import RealmSwift
final class RealmManager {
static let shared = RealmManager()
private init() {
configureRealm()
}
private func configureRealm() {
let config = Realm.Configuration(
schemaVersion: 1,
migrationBlock: { migration, oldSchemaVersion in
if oldSchemaVersion < 1 {
// Migration logic
}
}
)
Realm.Configuration.defaultConfiguration = config
}
var realm: Realm {
try! Realm()
}
}
// Models/Item+CoreDataClass.swift
import Foundation
import CoreData
@objc(Item)
public class Item: NSManagedObject {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Item> {
return NSFetchRequest<Item>(entityName: "Item")
}
@NSManaged public var id: UUID
@NSManaged public var title: String
@NSManaged public var createdAt: Date
@NSManaged public var isCompleted: Bool
@NSManaged public var category: Category?
}
extension Item {
static func create(
in context: NSManagedObjectContext,
title: String,
category: Category? = nil
) -> Item {
let item = Item(context: context)
item.id = UUID()
item.title = title
item.createdAt = Date()
item.isCompleted = false
item.category = category
return item
}
static func fetchAll(in context: NSManagedObjectContext) -> [Item] {
let request = fetchRequest()
request.sortDescriptors = [NSSortDescriptor(keyPath: \Item.createdAt, ascending: false)]
return (try? context.fetch(request)) ?? []
}
static func fetchIncomplete(in context: NSManagedObjectContext) -> [Item] {
let request = fetchRequest()
request.predicate = NSPredicate(format: "isCompleted == NO")
request.sortDescriptors = [NSSortDescriptor(keyPath: \Item.createdAt, ascending: false)]
return (try? context.fetch(request)) ?? []
}
}
// Data/Repository/ItemRepository.swift
import Foundation
import CoreData
import Combine
protocol ItemRepositoryProtocol {
func fetchItems() -> AnyPublisher<[Item], Error>
func addItem(title: String) -> AnyPublisher<Item, Error>
func updateItem(_ item: Item) -> AnyPublisher<Void, Error>
func deleteItem(_ item: Item) -> AnyPublisher<Void, Error>
}
final class ItemRepository: ItemRepositoryProtocol {
private let container: NSPersistentContainer
private let backgroundContext: NSManagedObjectContext
init(container: NSPersistentContainer = PersistenceController.shared.container) {
self.container = container
self.backgroundContext = container.newBackgroundContext()
self.backgroundContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
}
func fetchItems() -> AnyPublisher<[Item], Error> {
Future { [weak self] promise in
guard let self = self else { return }
self.backgroundContext.perform {
do {
let items = try Item.fetchAll(in: self.backgroundContext)
promise(.success(items))
} catch {
promise(.failure(error))
}
}
}
.eraseToAnyPublisher()
}
func addItem(title: String) -> AnyPublisher<Item, Error> {
Future { [weak self] promise in
guard let self = self else { return }
self.backgroundContext.perform {
let item = Item.create(in: self.backgroundContext, title: title)
do {
try self.backgroundContext.save()
promise(.success(item))
} catch {
self.backgroundContext.rollback()
promise(.failure(error))
}
}
}
.eraseToAnyPublisher()
}
func updateItem(_ item: Item) -> AnyPublisher<Void, Error> {
Future { [weak self] promise in
guard let self = self else { return }
self.backgroundContext.perform {
do {
try self.backgroundContext.save()
promise(.success(()))
} catch {
self.backgroundContext.rollback()
promise(.failure(error))
}
}
}
.eraseToAnyPublisher()
}
func deleteItem(_ item: Item) -> AnyPublisher<Void, Error> {
Future { [weak self] promise in
guard let self = self else { return }
self.backgroundContext.perform {
self.backgroundContext.delete(item)
do {
try self.backgroundContext.save()
promise(.success(()))
} catch {
self.backgroundContext.rollback()
promise(.failure(error))
}
}
}
.eraseToAnyPublisher()
}
}
// Models/TaskObject.swift
import RealmSwift
class TaskObject: Object, Identifiable {
@Persisted(primaryKey: true) var id: ObjectId
@Persisted var title: String = ""
@Persisted var dueDate: Date?
@Persisted var isCompleted: Bool = false
@Persisted var priority: Int = 0
@Persisted var tags: List<TagObject>
@Persisted(originProperty: "tasks") var project: LinkingObjects<ProjectObject>
convenience init(title: String, dueDate: Date? = nil, priority: Int = 0) {
self.init()
self.title = title
self.dueDate = dueDate
self.priority = priority
}
}
class TagObject: Object, Identifiable {
@Persisted(primaryKey: true) var id: ObjectId
@Persisted(indexed: true) var name: String = ""
@Persisted var color: String = "#000000"
}
class ProjectObject: Object, Identifiable {
@Persisted(primaryKey: true) var id: ObjectId
@Persisted var name: String = ""
@Persisted var tasks: List<TaskObject>
}
// Data/Repository/TaskRealmRepository.swift
import Foundation
import RealmSwift
import Combine
protocol TaskRepositoryProtocol {
func fetchTasks() -> AnyPublisher<[TaskObject], Error>
func addTask(_ task: TaskObject) -> AnyPublisher<Void, Error>
func updateTask(_ task: TaskObject, with updates: (TaskObject) -> Void) -> AnyPublisher<Void, Error>
func deleteTask(_ task: TaskObject) -> AnyPublisher<Void, Error>
}
final class TaskRealmRepository: TaskRepositoryProtocol {
private let realm: Realm
init(realm: Realm = RealmManager.shared.realm) {
self.realm = realm
}
func fetchTasks() -> AnyPublisher<[TaskObject], Error> {
Just(Array(realm.objects(TaskObject.self).sorted(byKeyPath: "dueDate")))
.setFailureType(to: Error.self)
.eraseToAnyPublisher()
}
func addTask(_ task: TaskObject) -> AnyPublisher<Void, Error> {
Future { [weak self] promise in
guard let self = self else { return }
do {
try self.realm.write {
self.realm.add(task)
}
promise(.success(()))
} catch {
promise(.failure(error))
}
}
.eraseToAnyPublisher()
}
func updateTask(_ task: TaskObject, with updates: (TaskObject) -> Void) -> AnyPublisher<Void, Error> {
Future { [weak self] promise in
guard let self = self else { return }
do {
try self.realm.write {
updates(task)
}
promise(.success(()))
} catch {
promise(.failure(error))
}
}
.eraseToAnyPublisher()
}
func deleteTask(_ task: TaskObject) -> AnyPublisher<Void, Error> {
Future { [weak self] promise in
guard let self = self else { return }
do {
try self.realm.write {
self.realm.delete(task)
}
promise(.success(()))
} catch {
promise(.failure(error))
}
}
.eraseToAnyPublisher()
}
}
swift-swiftui - iOS app developmentmobile-security - Secure data storageoffline-storage - Cross-platform offline patternsActivates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.