iPhone приложение отклонены, поскольку принципы хранения данных iCloud


Критическое исправление одного из моих приложений было недавно отклонено из-за предполагаемого нарушения правил хранения данных iCloud.

Вот как мое приложение хранит данные (не было проблем с момента утверждения первой версии моего приложения в 2009 году):

  1. при запуске он копирует базу данных" starter " SQLite3 из пакета приложений в папку Documents.
  2. база данных содержит базовую схему и некоторые примеры данных, чтобы пользователь мог видеть, как использовать приложение. Он маленький - чуть меньше 3 МБ.
  3. дальнейшая работа пользователя сохраняется только в этом файле базы данных. Они могут удалить или сохранить образцы, они могут добавить тонны своих собственных данных, но этот файл базы данных всегда будет там.
Обновление ранее в этом году было отклонено по той же причине, но когда я дал им объяснение выше, статус приложения изменился с "отклонено" на "в обзоре" на "обработка для App Store".- Они не прислали мне никаких объяснений, так что я подумал, что это просто недоразумение. со стороны рецензента. На этот раз рецензент ответил на мое объяснение, просто сказав, что не созданные пользователем данные не должны храниться в iCloud, и мое обновление остается в состоянии "отклонено". Но я не понимаю, что мне здесь делать. Поскольку вся работа пользователя хранится в базе данных, я не могу исключить ее из резервной копии iCloud или сохранить в папке кэша. Кроме того, я не могу четко отделить "генерируемые пользователем" от "непользовательские" данные, потому что приложение работает из одного и того же файла базы данных. Исходные, не созданные пользователем данные будут быстро заменены собственными данными пользователя, хотя имя файла и расположение каталога базы данных останутся прежними.

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

Это должно быть очень распространенное явление. проблема, но, к сожалению, это не нормально для меня, чтобы просто отключить резервное копирование-пользователи вкладывают много работы в данные, которые они хранят в моем приложении, и резервное копирование iCloud очень важно для них.

Какие варианты у меня есть на данный момент? Вот что я вижу:

  1. Снова свяжитесь с Apple и попытайтесь объяснить, что происходит.

  2. Могу ли я установить атрибут резервного копирования файла в значение нет, а затем переключить его только на Да, когда пользователь делает свое первое изменение? Это нормально технически и нормально с яблоком?

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

  4. Плачь.

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

Также очень удручает, что любые изменения, которые я внесу, потребуют еще одного раунда тестирования и обзора приложения, что отложит мое критическое обновление на дополнительные 2-3 недели. : /

UPDATE : может быть, есть другой вариант: можно ли просто сохранить файл в Library/ вместо Documents/, поскольку их проблема, похоже, связана именно с использованием папки Documents? Будет ли файл резервное копирование, если оно хранится в Library/?

Обновление 2 : больше всего меня смущает то, что любое приложение с поддержкой баз данных (даже если оно использует основные данные, я полагаю) должно будет создать файл базы данных, содержащий по крайней мере схему приложения. Проблема только в том, что размер моей базы данных слишком велик? Потому что я не вижу, как любое приложение с поддержкой баз данных может избежать необходимости создавать базу данных при запуске.

UPDATE 3 : я использую пользовательский уровень взаимодействия SQLite-нет основные данные. Кроме того, данные примера состоят из начальных изображений, которые пользователь, вероятно, в конечном итоге удалит, когда они начнут использовать приложение.

8 17

8 ответов:

3 МБ похоже на довольно много образцов данных, хранящихся в базе данных. Если вы вытащите изображения и сохраните ссылки на изображения в базе данных вместо этого, вы сможете значительно сократить это использование. Затем вы можете изменить код средства получения изображений в базе данных на что-то вроде этого:

- (UIImage *)image
{
    NSString *imageName = self.imageName;
    UIImage *image = [UIImage imageNamed:imageName];
    if (!image)
    {
        NSString *imageLibraryPath = ...;
        image = [UIImage imageWithPath:[imageLibraryPath stringByAddingPathComponent:imageName]];
    }
    return image;
}

- (void)setImage:(UIImage *)image
{
    [self setImageData:UIImagePNGRepresentation(image)];
}

- (void)setImageData:(NSData *)imageData
{
    NSString *imageLibraryPath = ...;
    NSString *fileName = self.uniqueId; //or something else, UUID maybe?
    NSString *filePath = [imageLibraryPath stringByAddingPathComponent:imageName];
    [imageData writeToFile:filePath atomically:YES]; // maybe dispatch_async this into the background?
    self.fileName = fileName;
}

self.fileName будет поддерживаться вашей базой данных.

Сократив таким образом объем хранилища данных, вы сможете получить одобрение, так как вы не храните относительно большие объемы данных на телефон. Изображения также могут быть в пакете приложений таким образом, и их не нужно дублировать вообще.

У меня есть очень глупая идея. Но, может быть, это действительно так.

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

Одним из обходных путей было бы чтение файла SQL из пакета, пока пользователь не попытается что-то изменить. Тогда перепишите его. Так как файл маленький, он не должен даже требовать спиннера.

У меня была именно такая проблема с Приложение недавно. В нашем случае мы использовали основные данные и скопировали файл SQL при запуске.

К сожалению, вы должны ориентироваться на iOS 5.

Https://developer.apple.com/library/ios/qa/qa1719/_index.html

Просто добавьте следующий атрибут, и Apple позволит вам пройти (если вы не используете

    #include <sys/xattr.h>
    ...
    - (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
    {
    int result = -1;
    @try {
            const char* filePath = [[URL path] fileSystemRepresentation];
            const char* attrName = "com.apple.MobileBackup";
            u_int8_t attrValue = 1;
            result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
    } @catch (NSException * e) {
            DebugLog(@"Exception: %@", e);
    }
    return result == 0;
    }

    - (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    ... 
    NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
    [self addSkipBackupAttributeToItemAtURL:storeUrl];
    ...

CoreData и два постоянных магазина должны быть способом пойти. Но для вас, при первом копировании файла установите com.яблоко.Атрибут файла MobileBackup. Снимите его после того, как пользователь внесет свою первую модификацию

В качестве окончательного решения я предлагаю использовать CoreData, с вашими законсервированными данными в качестве дополнительного постоянного хранилища только для чтения.

Тем не менее, в то же время, вам нужно простое и быстрое решение. Создайте простой экран, который загружает образцы данных в базу данных пользователя. Поместите ссылку на экран" система "или" инструмент", чтобы это можно было сделать в любое время.

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

Это должно помочь вам пройти проверку.

Использование вашего "частного" уровня доступа к данным SQL

Поскольку вы используете не основные данные, а пользовательский уровень доступа, я могу только предложить не помещать базу данных" initial seed " в папку iCloud, а написать пользовательскую процедуру, которая генерирует ее во время выполнения (например. при первом запуске приложения).

Наилучшим подходом будет размещение вашего реального файла SQL в общем пакете приложений, вне общей папки iCloud. Через вашу процедуру вы должны будете прочитать все содержание этот файл и воссоздать клон в общей папке, так что этот новый файл будет отображаться как пользовательский контент, а не в комплекте контента. Это потребует немного бесполезных накладных расходов, но я думаю, что это необходимо, чтобы избежать отказа Apple от вашего приложения.

Я предлагаю вам не делать резервные копии всех изображений и оставить их в основном пакете, если это возможно, так как они уже присутствуют в каждом загруженном приложении, а затем будут бесполезно занимать драгоценное пространство на iCloud. Попробуйте разместить в iCloud только то, что строго необходимо.

На случай, если вы планируете использовать Core Data и iCloud вместе.

Во-первых, размещение пользовательского файла базы данных SQLite3 в iCloud опасно по нескольким причинам, первая из которых заключается в том, что вы никогда не сможете должным образом обрабатывать проблемы слияния между различными данными, если ваше приложение используется на разных устройствах одновременно. Я не могу дать вам здесь полное решение, так как оно потребует слишком много времени и пространства. Но Я предлагаю вам посмотреть на сессию 227 talk от Apple WWDC в этом году. Они говорят об использовании основных данных и iCloud вместе, а также о решении той же проблемы, с которой вы столкнулись прямо сейчас (например, начальное заполнение базы данных и синхронизация через iCloud). Если вы зайдете на страницу WWDC через портал разработчика Apple, вы сможете получить полную копию образца проекта.

Если вы используете основные данные, вы можете сохранить образцы данных в пакете приложений. Откройте его как постоянное хранилище только для чтения на том же координаторе, что и хранилище чтения / записи в каталоге docs, и основные данные будут уверены, что все останется в правильном месте при сохранении. Об этом говорится в видеоролике WWDC 2012 "рекомендации по использованию основных данных".

Если вы используете SQLite напрямую, это не так просто, но вы можете реализовать свою собственную логику для этого.