Приведи пример основных операций (CRUD) с Core Data в iOS.

«Приведи пример основных операций (CRUD) с Core Data в iOS.» — вопрос из категории Базы данных, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Core Data — это фреймворк для управления графом объектов (ORM) и сохранения их на диск. Ниже приведены примеры базовых операций CRUD (Create, Read, Update, Delete).

Предположим, есть сущность Person с атрибутами name (String) и age (Int16).

1. Настройка Core Data Stack (обычно в AppDelegate или отдельном классе)

import CoreData

class CoreDataStack {
    static let shared = CoreDataStack()

    lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "YourDataModel")
        container.loadPersistentStores { description, error in
            if let error = error { fatalError("Unable to load store: (error)") }
        }
        return container
    }()

    var context: NSManagedObjectContext {
        return persistentContainer.viewContext // Контекст главного потока
    }

    func saveContext() {
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                print("Save error: (error)")
            }
        }
    }
}

2. Операции CRUD

C (Create) — Создание объекта

func createPerson(name: String, age: Int16) {
    let context = CoreDataStack.shared.context
    // Создаем новый управляемый объект в контексте.
    let newPerson = Person(context: context)
    newPerson.name = name
    newPerson.age = age

    // Сохраняем контекст, чтобы записать изменения в хранилище.
    CoreDataStack.shared.saveContext()
}

R (Read) — Чтение (Fetch) объектов

func fetchAllPeople() -> [Person] {
    let context = CoreDataStack.shared.context
    // Создаем запрос (FetchRequest) для сущности Person.
    let fetchRequest: NSFetchRequest<Person> = Person.fetchRequest()

    // Опционально: добавляем сортировку (NSSortDescriptor).
    let sortByName = NSSortDescriptor(key: "name", ascending: true)
    fetchRequest.sortDescriptors = [sortByName]

    // Опционально: добавляем предикат для фильтрации (NSPredicate).
    // fetchRequest.predicate = NSPredicate(format: "age > %@", NSNumber(value: 18))

    do {
        let people = try context.fetch(fetchRequest)
        return people
    } catch {
        print("Fetch failed: (error)")
        return []
    }
}

U (Update) — Обновление объекта

func updatePerson(_ person: Person, newName: String) {
    // Обновляем свойства существующего управляемого объекта.
    person.name = newPersonName
    // Сохраняем контекст.
    CoreDataStack.shared.saveContext()
}

D (Delete) — Удаление объекта

func deletePerson(_ person: Person) {
    let context = CoreDataStack.shared.context
    // Удаляем объект из контекста.
    context.delete(person)
    // Сохраняем контекст.
    CoreDataStack.shared.saveContext()
}

// Пример удаления всех объектов
func deleteAllPeople() {
    let context = CoreDataStack.shared.context
    let fetchRequest: NSFetchRequest<NSFetchRequestResult> = Person.fetchRequest()
    let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)

    do {
        try context.execute(deleteRequest) // Эффективно для массового удаления
        try context.save()
    } catch {
        print("Batch delete error: (error)")
    }
}

Важные best practices:

  • Работа с NSManagedObjectContext должна происходить в том потоке, в котором он был создан (viewContext — главный поток).
  • Для фоновых операций используйте persistentContainer.newBackgroundContext().
  • Всегда обрабатывайте ошибки при save() и fetch().
  • Используйте NSFetchedResultsController для эффективной привязки данных к UITableView или UICollectionView.