Подтвердить что ты не робот

Приложение iPhone отклонено из-за принципов хранения данных iCloud

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

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

  • При запуске он копирует "стартовую" базу данных SQLite3 из пакета приложений в папку "Документы".
  • База данных содержит базовую схему и некоторые данные примера, чтобы пользователь мог видеть, как использовать приложение. Он небольшой - чуть меньше 3 МБ.
  • Затем будущая работа пользователя сохраняется только в этом файле базы данных. Они могут удалять или хранить образцы, они могут добавлять тонны своих данных, но этот файл базы данных всегда будет там.

Обновление в начале этого года было отклонено по той же причине, но когда я дал им объяснение выше, статус приложения изменился с "Отклонено" на "В обзоре" на "Обработка для магазина приложений". Они не пришли мне никаких объяснений, поэтому я подумал, что это просто недоразумение в части рецензента.

На этот раз рецензент ответил на мое объяснение, просто сказав, что данные, не созданные пользователем, не должны храниться в iCloud, и мое обновление остается в состоянии "Отклонено".

Но я не понимаю, что я должен делать здесь. Поскольку вся работа пользователя хранится в базе данных, я не могу исключить это из резервной копии iCloud или сохранить ее в папке Cache. Кроме того, я не могу чисто отделить "пользовательские" от "неавторизированных" данных, потому что приложение работает из одного и того же файла базы данных. Исходные, не созданные пользователем данные будут быстро заменены собственными данными пользователя, хотя имя файла и расположение каталога базы данных будут оставаться прежними.

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

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

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

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

  • Могу ли я установить атрибут резервного копирования файла на NO, а затем переключать его только на YES, когда пользователь делает свое первое изменение? Это хорошо, технически и хорошо с Apple?

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

  • Cry.

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

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

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

ОБНОВЛЕНИЕ 2. То, что я нахожу наиболее запутанным, заключается в том, что любое приложение с поддержкой базы данных (даже если оно использует Core Data, я полагаю) должно будет создать файл базы данных, содержащий хотя бы схему приложения, Проблема в том, что размер моей базы данных слишком велик? Поскольку я не вижу, как любое приложение с поддержкой базы данных может избежать необходимости создания базы данных при запуске.

ОБНОВЛЕНИЕ 3. Я использую настраиваемый слой взаимодействия SQLite, а не Core Data. Кроме того, данные примера состоят из стартовых изображений, которые пользователь, вероятно, в конечном итоге удалит, когда они начнут использовать приложение.

4b9b3361

Ответ 1

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

- (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 будет поддерживаться вашей базой данных.

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

Ответ 2

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

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

Ответ 3

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

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

К сожалению, вам нужно настроить таргетинг на iOS 5.

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

Ответ 4

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

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

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

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

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

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

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

Ответ 5

Просто добавьте следующий атрибут, и 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];
    ...

Ответ 6

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

Ответ 7

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

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

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

Это должно пройти мимо обзора.

Ответ 8

Если вы используете Core Data, вы можете сохранить образцы данных в комплекте приложений. Откройте его как постоянное хранилище только для чтения на том же координаторе, что и хранилище чтения/записи в вашем каталоге документов, а Core Data будет следить за тем, чтобы все оставалось в нужном месте при сохранении. Это объясняется в видеоролике "Лучшие практики для использования основных данных" от WWDC 2012.

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