Ответ
Да, приходилось. Кастомные (тяжелые) миграции в Core Data необходимы, когда автоматическая лёгкая миграция (lightweight migration) невозможна. Это происходит при сложных изменениях схемы данных, таких как:
- Разделение одного атрибута на несколько.
- Объединение нескольких атрибутов в один.
- Нелинейные преобразования данных (например, изменение формата даты или вычисление нового значения на основе старых).
- Изменение иерархии сущностей (entity inheritance).
Процесс и пример:
Миграция выполняется с помощью NSEntityMigrationPolicy. Необходимо создать Mapping Model (.xcmappingmodel) и указать в нём кастомный класс политики.
Пример политики миграции для преобразования полного имени (fullName) в отдельные атрибуты firstName и lastName:
import CoreData
class SplitNameMigrationPolicy: NSEntityMigrationPolicy {
@objc func transformFullName(forFullName: NSString?) -> [String: String]? {
// Логика разделения строки
guard let fullName = forFullName as String? else { return nil }
let components = fullName.split(separator: " ").map(String.init)
let firstName = components.first ?? ""
let lastName = components.dropFirst().joined(separator: " ") // На случай двойных фамилий
return ["firstName": firstName, "lastName": lastName]
}
}
В Mapping Model для атрибута firstName в качестве Value Expression указывается: FUNCTION($entityPolicy, "transformFullNameForFullName:", $source.fullName)["firstName"].
Критически важные практики:
- Тестирование на копии реальной базы данных перед выпуском обновления приложения.
- Поэтапные миграции для очень больших изменений (версия 1 -> 2 -> 3).
- Обеспечение обратной совместимости и обработка
nil-значений. - Информирование пользователя о процессе, так как миграция может занять время.