Используя Хранилище SQLite с iCloud
Интеграция iCloud базовых Данных комбинирует SQLite-тип персистентный доступ хранилища с хранением iCloud. Следуйте стратегии реализации в этой главе для создания устойчивого, высокоэффективного поддерживающего iCloud приложения. Используя эти инструкции и пример кода, Вы будете учиться как:
Включите поддержку iCloud
Сохраните управляемые объекты к iCloud
Поймите изменение содержания и события доступности
Отберите исходные данные
Удалите двойные записи
Включение Поддержки iCloud
Чтобы начать использовать iCloud в Вашем приложении, необходимо сначала включить поддержку iCloud приложения в облаке и в проекте. Это эффективно соединяет два. После включения поддержки iCloud можно начать использовать контейнер повсеместности приложения, тестовую среду приложения в облаке. Вы выполняете две задачи добавить iCloud к новому Базовому приложению Данных:
Создайте приложение ID на портале разработчика.
Создайте приложение ID на iOS Центр Dev в developer.apple.com. Приложения, использующие iCloud, не могут использовать подстановочные идентификаторы. Установите свой проект в элемент кода с помощью Приложения ID, который Вы просто создали.
Включите iCloud в XCode.
Перейдите к цели своего приложения в настройках проекта в XCode и выберите область возможностей. Щелкните по переключателю, следующему за iCloud, как показано на рисунке 1-1. XCode конфигурирует Ваше Приложение ID в портале разработчика и добавляет права на Ваше приложение. Эти права дают Ваше разрешение приложения получить доступ к его контейнеру (ам) повсеместности. По умолчанию XCode создает один идентификатор контейнера повсеместности с помощью Приложения ID.
Добавление поддерживающего iCloud Персистентного Хранилища к Базовым Данным
После включения iCloud приложение может начать сохранять документы и данные к контейнеру повсеместности. При создании Данных Ядра SQLite-типа, персистентное хранилище с включенной поддержкой iCloud, Базовые Данные использует контейнер повсеместности для сохранения объектов модели к iCloud. Поэтому необходимо создать поддерживающее iCloud персистентное хранилище, чтобы начать использовать iCloud. Посмотрите Мигрирующие Пользовательские Данные к iCloud для дополнительных задач, которые должны быть выполнены при включении iCloud в существующем Базовом приложении Данных.
Поскольку Вы были бы для типичного Базового приложения Данных, добавлять NSSQLiteStoreType
введите хранилище своему персистентному координатору хранилища. Вы передаете следующую пару ключ/значение в словаре опций для включения iCloud.
NSPersistentStoreUbiquitousContentNameKey
NSString
объект с именем, используемым для идентификации хранилища:
NSURL *documentsDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; |
NSURL *storeURL = [documentsDirectory URLByAppendingPathComponent:@"CoreData.sqlite"]; |
NSError *error = nil; |
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:<# your managed object model #>]; |
NSDictionary *storeOptions = |
@{NSPersistentStoreUbiquitousContentNameKey: @"MyAppCloudStore"}; |
NSPersistentStore *store = [coordinator addPersistentStoreWithType:NSSQLiteStoreType |
configuration:nil |
URL:storeURL |
options:storeOptions |
error:&error]; |
NSURL *finaliCloudURL = [store URL]; |
Для описания дополнительных опций, которые могут быть указаны, посмотрите Ссылку класса NSPersistentStoreCoordinator.
Контрольная точка
В этой точке Ваше приложение может создать поддерживающие iCloud Базовые Данные персистентное хранилище. Вы включили iCloud в XCode, создали повсеместное довольное имя и добавили поддерживающее iCloud персистентное хранилище с тем именем к Вашему персистентному координатору хранилища.
Установка: Создайте Базовый Стек данных и добавьте персистентное хранилище с повсеместным довольным опция имени.
Тест: Выполните приложение на устройстве. Если Базовые Данные успешно создали и сконфигурированный поддерживающее iCloud персистентное хранилище, платформа регистрирует сообщение, содержащее “Используя локальное хранение: 1”, и, позже, другое сообщение, содержащее “Используя локальное хранение: 0”.
Реакция на События iCloud
когда изменения происходят с данными в контейнере повсеместности Вашего приложения или к доступности самого контейнера, iCloud уведомляет Базовую платформу Данных. После получения сообщений от iCloud Базовые Данные переводят эти универсальные изменения состояния в события, которые целесообразны в контексте Вашего Базового Стека данных и соответствующие применимым на практике шагам, которые Вы предпринимаете, чтобы усовершенствовать пользовательский интерфейс Вашего приложения. Базовые Данные говорят Ваше приложение об этих событиях с помощью уведомлений.
Перед реализацией ответов на события iCloud полезно помнить некоторые общие руководящие принципы.
Передайте соответствующего персистентного координатора хранилища как объект отфильтровать уведомления, которые получают Ваши обработчики. Иначе, Ваше приложение могло получить уведомления от других персистентных координаторов хранилища.
Вычеркните из списка для уведомлений, когда Ваш контроллер представления больше не будет экранным.
Отгрузка та, на очередь, на который Ваши жизни контекста или использование
performBlock:
API. Уведомления не могут быть отправлены на том же потоке как Ваш контекст управляемого объекта.Отгрузка на основной поток, когда Вы обновляете свой пользовательский интерфейс.
Особенно важно протестировать поддерживающее iCloud приложение для iOS на существующем устройстве. Средство моделирования iOS точно не моделирует использование iCloud при реальных условиях. Для получения дополнительной информации о тестировании Вашего приложения и решении проблем, посмотрите Поиск и устранение неисправностей.
Базовые данные конфигурируют Ваше персистентное хранилище
Первый случай iCloud происходит после того, как Вы добавите поддерживающее iCloud персистентное хранилище к своему персистентному координатору хранилища. Базовые Данные возвращают Ваше персистентное хранилище из вызова метода и сразу отправляют NSPersistentStoreCoordinatorStoresDidChangeNotification
уведомление, чтобы позволить Вашему приложению знать, что персистентное хранилище было сконфигурировано для использования. Пользовательский информационный словарь этого уведомления содержит создаваемый NSPersistentStore
объект. На рисунке 1-2 Ваше приложение добавляет поддерживающее iCloud персистентное хранилище, заставляющее Базовые Данные отправлять уведомление и начинать контейнерную установку. В обработчике для уведомления персистентное хранилище также доступно в пользовательском информационном словаре уведомления.
Контрольная точка
Когда поддерживающее iCloud персистентное хранилище готово к употреблению, в этой контрольной точке Вы сконфигурировали Базовые Данные для сообщения приложения. После добавления нового поддерживающего iCloud персистентного хранилища в предыдущем разделе Вы создали обработчик уведомления для ответа на NSPersistentStoreCoordinatorStoresDidChangeNotification
уведомления.
Установка: добавьте NSLog
оператор в Ваших хранилищах «обработчика уведомления действительно изменялся».
Тест: Полностью удалите свое приложение из Вашего устройства и затем щелкните по кнопке запуска в XCode, чтобы переустановить Ваше приложение и вновь открыть его. Если Базовые Данные успешно создали и сконфигурированный поддерживающее iCloud персистентное хранилище, платформа вызывает Ваш обработчик уведомления и Ваш NSLog
оператор распечатает к консоли в XCode.
iCloud Выполняет Разовую Установку
Когда пользователь запускает Ваше поддерживающее iCloud приложение впервые, Базовые Данные и система сотрудничают для создания контейнера повсеместности приложения. Инициализация контейнера повсеместности является продолжительной работой, полагающейся на сетевое соединение со службой iCloud. Из-за этого Базовая платформа Данных предоставляет Вам временное локальное персистентное хранилище, которое Вы используете, в то время как работа выполняется в фоновом режиме. На последующих запусках приложения уже инициализируется контейнер повсеместности, и Базовые Данные связаны с поддерживающим iCloud персистентным хранилищем.
Реакция на разовую установку
После того, как разовая установка завершена, Базовые Данные перемещают записи от временного локального персистентного хранилища до поддерживающего iCloud хранилища. Когда Базовые Данные заканчивают перемещать все Ваши данные, временное локальное хранилище и содержание Вашего контекста (ов) управляемого объекта недопустимы. Для подготовки Вас к этому событию Базовые Данные отправляют два уведомления после того, как это закончит перемещать Ваши данные: один непосредственно перед тем, как это выгружает хранилища и лишает законной силы Ваши данные и другое право после.
Как проиллюстрировано на рисунке 1-3, когда установка заканчивается, Базовые Данные отправляют NSPersistentStoreCoordinatorStoresWillChangeNotification
уведомление. В Вашем обработчике уведомления Вы сбрасываете свой контекст управляемого объекта и отбрасываете любые ссылки на существующие управляемые объекты. Как только Ваш обработчик заканчивает выполняться, эти объекты больше не действительны. Необходимо также предотвратить любое взаимодействие с временным локальным хранилищем в то время как Базовые переходы Данных к поддерживающему iCloud хранилищу. Отключение Вашего пользовательского интерфейса является самым простым способом сделать это в управляемом UI приложении и в большинстве случаев невидимо для пользователя. Это вызвано тем, что время между уведомлением-изменения и уведомлением-изменения чрезвычайно коротко.
[[NSNotificationCenter defaultCenter] |
addObserverForName:NSPersistentStoreCoordinatorStoresWillChangeNotification |
object:self.managedObjectContext.persistentStoreCoordinator |
queue:[NSOperationQueue mainQueue] |
usingBlock:^(NSNotification *note) { |
[self.managedObjectContext performBlock:^{ |
[self.managedObjectContext reset]; |
}]; |
// drop any managed object references |
// disable user interface with setEnabled: or an overlay |
}]; |
Базовые Данные заканчивают выгружать временное локальное хранилище с поддерживающим iCloud хранилищем и отправляют NSPersistentStoreCoordinatorStoresDidChangeNotification
уведомление. Пользовательский информационный словарь уведомления содержит поддерживающее iCloud хранилище как объект, связанный с NSAddedPersistentStoresKey
ключ. В обработчике этого уведомления Вы повторно включаете свой пользовательский интерфейс и перевыборку.
Контрольная точка
Когда разовая установка закончена, в этой точке Ваши обработчики уведомления отключают, включают, и обновляют Ваш пользовательский интерфейс. Вы зарегистрировались для NSPersistentStoreCoordinatorStoresWillChangeNotification
уведомления, где Вы отключаете свой пользовательский интерфейс. Вы также зарегистрировались для NSPersistentStoreCoordinatorStoresDidChangeNotification
уведомления, где Вы повторно включаете пользовательский интерфейс своего приложения и повторно выбираете Ваши данные.
Установка: На Вашем устройстве на iOS начните с включенного авиарежима. Если Вы создаете приложение Mac, отключаете каждый сетевой интерфейс вместо этого. Полностью удалите свое приложение из Вашего устройства также.
Тест: Выполните свое приложение и создайте несколько записей. Отключите авиарежим или повторно включите сетевой интерфейс и ожидайте Базовых Данных для печати “Используя локальное хранение: 0” к консоли в XCode. Базовые Данные вызывают Ваши обработчики уведомления, и Ваши записи исчезают. В следующем разделе Вы изучите, как сохранить изменения в памяти.
Сохранение изменений в памяти
Если Ваш контекст управляемого объекта имеет изменения, не посвятившие себя временному хранилищу, сохраните те изменения так, чтобы Базовые Данные переместили их на поддерживающее iCloud персистентное хранилище. Ваш обработчик уведомления ведет себя немного по-другому: вместо того, чтобы сразу сбрасывать Ваш контекст управляемого объекта, Вы проверяете на изменения в Вашем контексте управляемого объекта и вызываете save:
. Иначе, Вы следуете за тем же процессом, как описано в предыдущем разделе, сбрасывая Ваш контекст и отключая Ваш пользовательский интерфейс.
После сохранения Вашего контекста управляемого объекта Базовые Данные отправляют другого NSPersistentStoreCoordinatorStoresWillChangeNotification
уведомление. Базовые Данные продолжают отправлять это уведомление, пока Вы больше не вызываете save:
на Вашем контексте управляемого объекта и вместо этого сбросе это. Этот цикл проиллюстрирован выше на рисунке 1-4 и реализован ниже.
[[NSNotificationCenter defaultCenter] |
addObserverForName:NSPersistentStoreCoordinatorStoresWillChangeNotification |
object:self.managedObjectContext.persistentStoreCoordinator |
queue:[NSOperationQueue mainQueue] |
usingBlock:^(NSNotification *note) { |
// disable user interface with setEnabled: or an overlay |
[self.managedObjectContext performBlock:^{ |
if ([self.managedObjectContext hasChanges]) { |
NSError *saveError; |
if (![self.managedObjectContext save:&saveError]) { |
NSLog(@"Save error: %@", saveError); |
} |
} else { |
// drop any managed object references |
[self.managedObjectContext reset]; |
} |
}]; |
}]; |
Контрольная точка
Когда разовая установка закончена, обработчики уведомления Вашего приложения отключают, включают и обновляют Ваш пользовательский интерфейс. Вы зарегистрировались для NSPersistentStoreCoordinatorStoresWillChangeNotification
и NSPersistentStoreCoordinatorStoresDidChangeNotification
уведомления для обработки перехода между временным локальным хранилищем и поддерживающим iCloud персистентным хранилищем после первоначальной установки контейнера повсеместности заканчиваются.
Установка: Начните с авиарежима, включенного на Вашем устройстве на iOS или всех сетевых интерфейсах, отключенных на Вашем Mac. Полностью удалите свое приложение из Вашего устройства также.
Тест: Выполните свое приложение и создайте несколько записей. Отключите авиарежим или повторно включите сетевой интерфейс. Тогда ожидайте Базовых Данных для печати “Используя локальное хранение: 0” к консоли в XCode. Базовые Данные вызывают Ваши обработчики уведомления, и Ваши записи сохраняются после того, как Ваш обработчик уведомления выполняет новый запрос выборки.
Базовые Изменения Содержания Сообщений Данных от iCloud
В то время как Ваше приложение работает, базовые изменения импорта Данных сохранились к iCloud от других коллег после первоначальной установки и. Базовые Данные представляют это событие как показано на рисунке 1-5.
Когда контейнер повсеместности получает изменения от iCloud, Базовые Данные отправляют NSPersistentStoreDidImportUbiquitousContentChangesNotification
уведомление. Это уведомление userInfo
словарь структурирован так же к тому из NSManagedObjectContextDidSaveNotification
уведомление за исключением этого это содержит NSManagedObjectID
экземпляры, а не NSManagedObject
экземпляры. Поэтому можно объединиться в изменениях от других коллег таким же образом, что Вы объединяете изменения от других контекстов управляемого объекта. Вызвать mergeChangesFromContextDidSaveNotification:
на Вашем контексте управляемого объекта, передающем в объекте уведомления, отправляется Базовыми Данными.
[[NSNotificationCenter defaultCenter] |
addObserverForName:NSPersistentStoreDidImportUbiquitousContentChangesNotification |
object:self.managedObjectContext.persistentStoreCoordinator |
queue:[NSOperationQueue mainQueue] |
usingBlock:^(NSNotification *note) { |
[self.managedObjectContext performBlock:^{ |
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:note]; |
}]; |
}]; |
Когда платформа импортирует существующие записи из iCloud, базовые Данные также отправят один или больше этих уведомлений после создания или восстановления персистентного хранилища и. Посмотрите, что Базовые Данные Помогают Вам с Переходами Учетной записи для получения дополнительной информации.
Контрольная точка
В этой контрольной точке обработчик уведомления изменения Вашего приложения объединяет изменения от других коллег в Ваш контекст управляемого объекта. Вы зарегистрировались для NSPersistentStoreDidImportUbiquitousContentChangesNotification
уведомление, где Вы решаете который данные обновляющая стратегия использовать — слияние в памяти или перевыборка данных.
Установка: Установите свое приложение на двух устройствах.
Тест: Выполните свое приложение на обоих устройствах и создайте несколько отличных записей на каждом. Ожидайте Базовых Данных для печати “Используя локальное хранение: 0” к консоли в XCode. Уведомления об изменении контента обычно следуют вскоре после, и каждое устройство добавляет записи других.
Базовые данные помогают Вам с переходами учетной записи
Переходы учетной записи могут повлиять на все данные Вашего приложения. Переход происходит для всех следующих четырех событий: начальный импорт от iCloud завершился, учетная запись iCloud, связанная с изменениями устройства, iCloud отключен, или пользователь удаляет данные Вашего приложения.
Реакция для учета переходов
В то время как Ваше приложение работает, Базовые работы Данных с Вашим приложением для подготовки к событию, когда система сообщает Базовым Данным о переходе учетной записи. Рисунок 1-6 показывает временную шкалу события перехода учетной записи.
Так же, как во время разовой установки, Базовые Данные отправляют NSPersistentStoreCoordinatorStoresWillChangeNotification
уведомление, сообщая Вам, что переход учетной записи происходит. В дополнение к добавленным и удаленным персистентным хранилищам, уведомление userInfo
словарь также содержит тип перехода. Тип перехода, связанный с NSPersistentStoreUbiquitousTransitionTypeKey
ключ, NSNumber
объект отобразился на ключ NSPersistentStoreUbiquitousTransitionType
перечисление. Можно использовать эту информацию для обнаружения, почему происходит переход.
В Вашем обработчике уведомления Вы сбрасываете свой контекст управляемого объекта и отбрасываете любые ссылки на существующие управляемые объекты. Как только Ваш обработчик заканчивает выполняться, эти объекты больше не действительны. В то время как Базовые Данные заканчивают переходить, необходимо также предотвратить любое взаимодействие с поддерживающим iCloud хранилищем. В управляемом UI приложении, отключая Ваш пользовательский интерфейс самый простой способ сделать это. Когда текущая учетная запись iCloud удалена, Базовые Данные сохраняют Ваше хранилище к специфичному для учетной записи архиву. Если пользователь подписывается в ту же учетную запись снова в будущем, Базовые Данные разархивировали данные и продолжают загружать.
Сохранение изменений в памяти
Поскольку это вело себя в первоначальной установке, Базовые Данные дают Вашему приложению шанс сохранить данные, не сохраненные к тому времени, когда уведомление было отправлено. Снова, потому что iOS удаляет старые хранилища, связанные с учетными записями iCloud, которые больше не активны на устройстве, Ваши изменения никогда не могут сохраняться или отправляться в облако.
В отличие от того, как это вело себя в разовой установке, Базовые Данные дают Вашему приложению только один шанс сохранить; это не отправит другого NSPersistentStoreCoordinatorStoresWillChangeNotification
уведомление. Как проиллюстрировано на рисунке 1-7 выше, сохраняя Ваш контекст управляемого объекта не вызывает цикл.
Контрольная точка
В этой точке два обработчика уведомления изменения хранилища Вашего приложения корректно переходят Ваше приложение между персистентными хранилищами, поскольку учетная запись iCloud добавлена или удалена. Вы изменили свои существующие обработчики уведомления для проверки NSPersistentStoreUbiquitousTransitionType
и ответьте соответственно.
Установка: Установите свое приложение на устройстве с включенным iCloud.
Тест: Выполните свое приложение на обоих устройствах и создайте несколько отличных записей. Ожидайте Базовых Данных для печати “Используя локальное хранение: 0” к консоли в XCode. Тогда измените учетные записи iCloud — данные Вашего приложения должны исчезнуть, и Ваше персистентное хранилище должно быть восстановлено с новыми данными учетной записи iCloud.
Исходные данные отбора
Если Ваше приложение упаковывается с предварительно созданной базой данных или если предыдущая версия Вашего приложения не сохранялась к iCloud, Ваш персистентный координатор хранилища может создать поддерживающее iCloud персистентное хранилище и переместить записи на единственном шаге. Для изучения, когда хранить отобранные данные в iCloud посмотрите Хранилище Только Существенные Данные в iCloud.
После создания Вашего персистентного координатора хранилища и добавления Вашего существующего персистентного хранилища, выполните те же шаги в Добавлении поддерживающего iCloud Персистентного Хранилища к Базовым Данным, заменив вызов к addPersistentStoreWithType:configuration:URL:options:error:
с вызовом к migratePersistentStore:toURL:options:withType:error:
. Передайте в своем существующем персистентном хранилище как первый параметр в методе. Миграция персистентного хранилища является синхронной задачей, в отличие от добавления поддерживающего iCloud персистентного хранилища. Вы диспетчеризируете миграцию на очередь фоновых задач и затем обновляете Ваш пользовательский интерфейс после того, как миграция будет завершена.
Наконец, отметьте отбор как полное использование хранение значения ключа iCloud так, чтобы другие коллеги не отбирали те же данные. Посмотрите Разработку для Данных Значения ключа в iCloud в Руководстве по проектированию iCloud для больше об использовании хранения значения ключа iCloud.
NSURL *documentsDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; |
NSURL *storeURL = [documentsDirectory URLByAppendingPathComponent:@"CoreData.sqlite"]; |
NSError *error = nil; |
NSPersistentStoreCoordinator *coord = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:<# your managed object model #>]; |
NSUbiquitousKeyValueStore *kvStore = [NSUbiquitousKeyValueStore defaultStore]; |
if (![kvStore boolForKey:@"SEEDED_DATA"]) { |
NSURL *seedStoreURL = <# path to your seed store #> |
NSError *seedStoreError; |
NSDictionary *seedStoreOptions = @{NSReadOnlyPersistentStoreOption: @YES}; |
NSPersistentStore *seedStore = |
[coord addPersistentStoreWithType:<#seed store type#> |
configuration:nil |
URL:seedStoreURL |
options:seedStoreOptions |
error:&seedStoreError]; |
NSDictionary *iCloudOptions = |
@{NSPersistentStoreUbiquitousContentNameKey: @"MyAppCloudStore"}; |
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; |
[queue addOperationWithBlock:^{ |
NSPersistentStore *iCloudStore = |
[coord migratePersistentStore:seedStore |
toURL:storeURL |
options:iCloudOptions |
withType:NSSQLiteStoreType |
error:&error]; |
NSURL *finaliCloudURL = [iCloudStore URL]; |
[kvStore setBool:YES forKey:@"SEEDED_DATA"]; |
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; |
[mainQueue addOperationWithBlock:^{ |
// Update your user interface |
}]; |
}); |
} else { |
// Add persistent store normally |
} |
Обнаружение и удаление двойных записей
Когда пользователь взаимодействует с Вашим приложением на многократных устройствах, Ваше приложение может закончить тем, что имело два или больше из тех же управляемых объектов. Для решения этой проблемы следующие шаги объясняют, как обнаружить и удалить двойные объекты. Дедупликация является процессом нахождения и удаления этих копий. Существует несколько общих ситуаций, в которых Ваше приложение должно выполнить дедупликацию:
Ваше приложение отобрало исходные данные.
Ваши пользователи часто создают те же записи на многократных коллегах.
Ваше приложение было обновлено от версии без поддержки iCloud, и Вы переместили существующие данные.
Например, пользователь хранит рецепты в приложении рецепта на двух коллегах. Поскольку первая версия приложения не поддерживала iCloud, пользователь создал те же рецепты на обоих устройствах. Пользователь обновляет приложение на обеих коллегах для управления версиями два, который теперь поддерживает интеграцию iCloud. После миграции рецептов пользователя к iCloud оба устройства имеют двойные рецепты.
В каждой из этих ситуаций задачами, которые Вы выполняете, является то же:
Выберите свойство или хеш многократных свойств для использования в качестве уникального идентификатора для каждой записи.
NSString *uniquePropertyKey = <# property to use as a unique ID #>
NSExpression *countExpression = [NSExpression expressionWithFormat:@"count:(%@)", uniquePropertyKey];
NSExpressionDescription *countExpressionDescription = [[NSExpressionDescription alloc] init];
[countExpressionDescription setName:@"count"];
[countExpressionDescription setExpression:countExpression];
[countExpressionDescription setExpressionResultType:NSInteger64AttributeType];
NSManagedObjectContext *context = <# your managed object context #>
NSEntityDescription *entity = [NSEntityDescription entityForName:@"<# your entity #>" inManagedObjectContext:context];
NSAttributeDescription *uniqueAttribute = [[entity attributesByName] objectForKey:uniquePropertyKey];
Выберите число раз, каждое уникальное значение появляется в хранилище.
Контекст возвращает массив словарей, каждый содержащий оценивающие уникальное значение и число раз появился в хранилище.
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"<# your entity #>"];
[fetchRequest setPropertiesToFetch:@[uniqueAttribute, countExpression]];
[fetchRequest setPropertiesToGroupBy:@[uniqueAttribute]];
[fetchRequest setResultType:NSDictionaryResultType];
NSArray *fetchedDictionaries = <# execute a fetch request against your store #>
Отфильтруйте уникальные значения, не имеющие никаких копий.
NSMutableArray *valuesWithDupes = [NSMutableArray array];
for (NSDictionary *dict in fetchedDictionaries) {
NSNumber *count = dict[@"count"];
if ([count integerValue] > 1) {
[valuesWithDupes addObject:dict[@"<# property used as the unique ID #>"]];
}
}
Используйте предикат для выборки всех записей с копиями.
Используйте дескриптор вида для надлежащего упорядочивания результатов для алгоритма победителя на следующем шаге.
NSFetchRequest *dupeFetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"<# your entity #>"];
[dupeFetchRequest setIncludesPendingChanges:NO];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"<# property used as the unique ID #> IN (%@)", valuesWithDupes];
[dupeFetchRequest setPredicate:predicate];
Выберите победителя.
После получения всех копий решает Ваше приложение, которые сохранить. Это решение должно быть детерминировано, означая, что каждая коллега должна всегда выбирать того же победителя. Среди других методов Ваше приложение могло сохранить создаваемую или измененную в последний раз метку времени для каждой записи и затем решить на основе этого.
MyClass *prevObject;
for (MyClass *duplicate in dupes) {
if (prevObject) {
if ([duplicate.uniqueProperty isEqualToString:prevObject.uniqueProperty]) {
if ([duplicate.createdTimestamp compare:prevObject.createdTimestamp] == NSOrderedAscending) {
[context deleteObject:duplicate];
} else {
[context deleteObject:prevObject];
prevObject = duplicate;
}
} else {
prevObject = duplicate;
}
} else {
prevObject = duplicate;
}
}
Не забудьте устанавливать объем партии на выборке и каждый раз, когда Вы достигаете конца пакета, сохраняете контекст.
Контрольная точка
В этой точке Ваше приложение может детерминировано удалить двойные записи.
Установка: Откройте предыдущее не, iCloud включил версию Вашего приложения на двух устройствах.
Тест: Создайте несколько из тех же записей на обоих устройствах. Обновление к новой версии приложения на обоих устройствах. После того, как оба устройства переместили свои хранилища на iCloud (см. Мигрирующие Пользовательские Данные к iCloud для больше о миграции), дедупликация была выполнена, и оба устройства передали эти изменения в iCloud, проверьте, чтобы удостовериться, что нет никакой копии или недостающих записей.
Выполнение миграций схемы
Во время разработки Вашего приложения и между версиями, можно изменить Базовую Модель данных, определяющую объекты. Можно использовать вызванную миграцию схемы процесса для миграции существующих данных приложения для использования новой модели. При использовании хранилища SQLite с iCloud хранилище поддерживает только легкую миграцию. (Для больше о легкой миграции, посмотрите Легкую Миграцию в Базовом Руководстве по программированию Управления версиями и Миграции данных Модели данных.), Поскольку поддерживающие iCloud Базовые приложения Данных не могут сохранить изменения между различными версиями Вашего приложения, использующими использование различные схемы, Ваше приложение нагонит, и ранее также новые версии объединятся в изменениях более старой версии только после того, как это было обновлено к той же версии.
NSURL *documentsDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; |
NSURL *storeURL = [documentsDirectory URLByAppendingPathComponent:@"CoreData.sqlite"]; |
NSError *error = nil; |
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:<# your managed object model #>]; |
NSDictionary *storeOptions = @{NSPersistentStoreUbiquitousContentNameKey: @"MyAppCloudStore", |
NSMigratePersistentStoresAutomaticallyOption: @YES, |
NSInferMappingModelAutomaticallyOption: @YES}; |
NSPersistentStore *store = [coordinator addPersistentStoreWithType:NSSQLiteStoreType |
configuration:nil |
URL:storeURL |
options:storeOptions |
error:&error]; |
NSURL *finaliCloudURL = [store URL]; |
Контрольная точка
В этой точке Ваше приложение может гладко выполнить миграции схемы с поддерживающим iCloud персистентным хранилищем.
Установка: Создайте вторую версию своего приложения с обновленной схемой, это совместимо с легкой миграцией.
Тест: Установите первую версию приложения на устройстве. Выполните действия, создающие записи и устанавливающие атрибуты, отличающиеся во второй версии Вашей схемы. Используйте второе устройство, выполняющее ту же версию приложения, чтобы проверить, что записи были сохранены к iCloud. Тогда установите и выполните обновленную версию приложения на Вашем устройстве. Проверьте, что записи мигрировали правильно.
Удаление поддерживающего iCloud Персистентного Хранилища
При разработке приложения (и иногда в реальном использовании), Вы, возможно, должны были бы временно или постоянно удалили бы свое поддерживающее iCloud персистентное хранилище. Существует три вида удаления хранилища: первое, восстанавливая от iCloud, удаляет локальное хранилище и воссоздает его от данных в iCloud. Вторая, отключающая персистентность iCloud, говорит Базовым Данным прекращать сохранять локальные данные к iCloud и не удаляет данных. Наконец, запуск вытирает данные Вашего приложения с Ваших устройств и с iCloud и является безусловно самым разрушительным.
Восстановление от iCloud
Чтобы удалить локальные данные и запуститься новый с существующих записей в iCloud, передайте NSPersistentStoreRebuildFromUbiquitousContentOption
опция со значением @YES
когда Вы добавляете свое поддерживающее iCloud персистентное хранилище к персистентному координатору хранилища. Включайте любые опции iCloud, которые Вы обычно включаете.
Отключение Персистентности iCloud
Чтобы мешать Вашему хранилищу сохраниться к iCloud, Вы просто не опускаете NSPersistentStoreUbiquitousContentNameKey
опция, когда Вы добавляете свое персистентное хранилище. Чтобы полностью удалить повсеместные метаданные и отключить персистентность iCloud, вместо этого переместите свое хранилище на новое расположение и передайте NSPersistentStoreRemoveUbiquitousMetadataOption
опция со значением @YES
в Вашем вызове к migratePersistentStore:toURL:options:withType:error:
.
Запуск
Для удаления хранилища постоянно из iCloud и каждой коллеги (включая текущее устройство) вызовите removeUbiquitousContentAndPersistentStoreAtURL:options:error:
метод класса для NSPersistentStoreCoordinator
класс. Этот метод синхронен, полагается на сетевую достижимость и потенциально продолжителен. Вы не должны использовать свое персистентное хранилище до возвратов метода. В той точке, Базовых переходах Данных к пустому хранилищу.