iPhone и Core Data: как сохранить введенные пользователем данные между обновлениями? - PullRequest
5 голосов
/ 11 марта 2010

Рассмотрим приложение для iPhone, которое представляет собой каталог животных. Приложение должно позволять пользователю добавлять пользовательскую информацию для каждого животного - скажем, оценку (по шкале от 1 до 5), а также некоторые заметки, которые они могут ввести о животном. Тем не менее, пользователь не сможет изменять данные о животных. Предположим, что когда приложение обновляется, для (статической) части каталога должно быть легко измениться, но мы бы хотели, чтобы (динамическая) часть пользовательской информации сохранялась между обновлениями, чтобы пользователь не потерял ни одного из их пользовательская информация.

Возможно, мы захотим использовать Core Data для создания этого приложения. Скажем также, что у нас уже есть предыдущий процесс для чтения данных животных для предварительного заполнения резервного хранилища (SQLite), которое использует Core Data. Мы можем встроить этот файл базы данных в сам пакет приложений, поскольку он не изменяется. Когда пользователь загружает обновление для приложения, новая версия будет включать в себя последнюю (статическую) базу данных каталога животных, поэтому нам не нужно беспокоиться о том, что она устарела.

Но теперь сложная часть: как мы можем хранить (динамические) пользовательские пользовательские данные в звуковой форме?

Сначала я подумал, что (динамическая) база данных должна храниться в каталоге Documents для приложения, чтобы обновления приложения не загромождали существующие данные. Я прав?

Моя вторая мысль заключается в том, что, поскольку (динамическая) база данных пользовательских данных не находится в том же хранилище, что и (статический) каталог животных, мы не можем наивно установить связь между сущностями Rating и Notes (в одной базе данных). ) и сущность Животное (в другой базе данных). В этом случае я бы предположил, что одним из решений было бы иметь строковое свойство animalName в сущности Rating / Notes и сопоставлять его во время выполнения. Это лучший способ сделать это, или есть способ "синхронизировать" две разные базы данных в Core Data?

Ответы [ 3 ]

2 голосов
/ 28 марта 2010

Вот как я в итоге решил эту проблему.

Хотя ответы Амории и М. Харрисона были верны, у них было одно предположение: после создания не только таблицы, но и каждая строка в каждой таблице всегда будут одинаковыми.

Проблема в том, что мой процесс предварительного заполнения базы данных «Животные» с использованием существующих данных (которые периодически обновляются) каждый раз создает новый файл базы данных. Другими словами, я не могу полагаться на создание связи между (статической) сущностью Animal и (динамической) сущностью Rating в Базовых данных, так как эта сущность может не существовать при следующей регенерации приложения. Почему бы и нет? Потому что я не контролирую, как Core Data хранит эти отношения за кулисами. Поскольку это хранилище резервных копий SQLite, вполне вероятно, что оно использует таблицу с отношениями внешних ключей. Но когда вы регенерируете базу данных, вы не можете предположить, какие значения получает каждая строка для ключа. Во второй раз первичный ключ для Lion может отличаться, если я добавлю лемура в список.

Единственный способ избежать этой проблемы - предварительно заполнить базу данных только один раз, а затем вручную обновлять строки при каждом обновлении. Однако в моем случае такой процесс не возможен.

Так в чем же решение? Ну, поскольку я не могу полагаться на отношения с внешними ключами, которые устанавливают Core Data, я должен создать свои собственные. То, что я делаю, представляет собой промежуточный этап в процессе генерации моей базы данных: вместо того, чтобы брать мои необработанные данные (которые являются текстом UTF-8, но на самом деле являются файлами MS Word) и создавать базу данных SQLite непосредственно с Core Data, я представляю посредника шаг: я конвертирую .txt в .xml. Почему XML? Ну, не потому, что это серебряная пуля, а просто потому, что это формат данных, который я могу очень легко разобрать. Так чем же отличается этот XML-файл? Значение хеша, которое я генерирую для каждого животного, используя MD5, которое я буду считать уникальным. Для чего нужно значение хеша? Теперь я могу создать две базы данных: одну для «статических» данных Animal (для которой у меня уже есть процесс), а другую для «динамической» базы данных Ratings, которую создает приложение для iPhone и которая находится в каталоге Documents приложения. , Для каждого рейтинга я создаю псевдосвязь с животным, сохраняя хэш-значение сущности животного. Поэтому каждый раз, когда пользователь открывает подробное представление Animal на iPhone, я запрашиваю «динамическую» базу данных, чтобы найти, существует ли сущность Rating, которая соответствует значению Animal.md5Hash.

Поскольку я сохраняю этот промежуточный файл данных XML, в следующий раз, когда будет обновление, я смогу сравнить его с последним файлом XML, который я использовал, чтобы увидеть, что изменилось. Теперь, если имя животного было изменено - скажем, опечатка была исправлена ​​- я возвращаю значение хеш-функции для этого животного на месте. Это означает, что даже если имя животного будет изменено, я все равно смогу найти соответствующий рейтинг, если он существует, в «динамической» базе данных.

У этого решения есть еще один приятный побочный эффект: мне не нужно решать какие-либо проблемы с миграцией. «Статическая» база данных Animal, которая поставляется вместе с приложением, может оставаться встроенной в качестве ресурса приложения. Это может изменить все, что он хочет. В какой-то момент «динамическая» база данных рейтингов может нуждаться в миграции, если я изменю ее модель данных, чтобы добавить больше сущностей, но в действительности две модели данных остаются полностью независимыми.

1 голос
/ 11 марта 2010

Хранение базы данных SQLite в каталоге Documents (NSDocumentDirectory) - это, безусловно, правильный путь. В общем, вам следует избегать изменений приложения, которые максимально изменяют или удаляют таблицы SQL (добавление в порядке). Однако, когда вам абсолютно необходимо внести изменения в обновление, сработает что-то вроде того, что сказал Аморя - откройте старую БД, импортируйте все, что вам нужно, в новую БД и удалите старую.

Поскольку звучит так, как будто вам нужна статическая база данных с таблицей «Животное», которую нельзя изменить, то простая замена этой таблицы обновлениями не должна быть проблемой - до тех пор, пока идентификатор записей не будет менять. Чтобы хранить пользовательские данные о животных, нужно создать отношение с внешним ключом к идентификатору животного для каждой записи, которую создает пользователь. Это то, что вам нужно будет перенести, когда обновление изменит его.

1 голос
/ 11 марта 2010

Я делаю это так: отправляю базу статических данных как часть вашего комплекта приложений. При запуске приложения проверьте наличие файла базы данных в Документах. Если нет, скопируйте один из комплекта приложения в Документы. Затем откройте базу данных из Documents: это единственная, с которой вы читаете и редактируете.

Когда произойдет обновление, новый статический контент необходимо будет объединить с редактируемой базой данных пользователя. Каждый статический элемент (в вашем случае это Animal) имеет поле factoryID, которое является уникальным идентификатором. При первом запуске после обновления загрузите базу данных из пакета приложения и выполните итерацию по каждому животному. Для каждого найдите соответствующую запись в рабочей базе данных и при необходимости обновите все поля.

Возможно, существует более быстрое решение, но поскольку процесс обновления происходит не слишком часто, то затраченное время не должно быть слишком проблематичным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...