NSURLIsExcludedFromBackupKey - приложения должны следовать рекомендациям по хранению данных iOS, иначе они будут отклонены
Мое приложение было отклонено, потому что кажется, что 7 МБ хранятся в папке с документами и автоматически отправляются в icloud. Таким образом, я зациклил все файлы, которые будут записаны в папку документов, с помощью этого метода:
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL {
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
if (&NSURLIsExcludedFromBackupKey == nil) {
// iOS 5.0.1 and lower
u_int8_t attrValue = 1;
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result == 0;
}
else {
// First try and remove the extended attribute if it is present
int result = getxattr(filePath, attrName, NULL, sizeof(u_int8_t), 0, 0);
if (result != -1) {
// The attribute exists, we need to remove it
int removeResult = removexattr(filePath, attrName, 0);
if (removeResult == 0) {
NSLog(@"Removed extended attribute on file %@", URL);
}
}
// Set the new key
NSError *error = nil;
[URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
return error == nil;
}
Версия 1.1 моего приложения была одобрена после реализации этого кода. На прошлой неделе я попытался отправить версию 1.2 того же приложения (ничего не изменилось в управлении файлами, все файлы, которые хранятся в папке документов, зацикливаются с помощью метода addSkipBackupAttributeToItemAtURL). Мое приложение было отклонено снова по той же причине. Я не могу переместить мой файл во временную или кеш-папку, потому что мое приложение не может полностью восстановить файл (один из этих файлов - это БД, восстановление БД означает потерю данных, вставленных пользователем), поэтому этот не может быть решением, Во всяком случае, я нашел проблему в коде, вот как я вызываю метод:
[self addSkipBackupAttributeToItemAtURL: [NSURL fileURLWithPath:fullPath]];
использование устройства [NSURL fileURLWithPath:fullPath] с ios 5.1 возвращает ошибку, и кажется, что создать атрибут невозможно. Если я изменяю инициализацию nsurl с помощью [NSURL URLWithString:defaultStorePath], устройство с 5.1, кажется, правильно добавляет атрибут.
В ios 5.0.1 все инвертировано, [NSURL URLWithString:defaultStorePath] возвращает ошибку, пока [NSURL fileURLWithPath:fullPath] работает.
Может быть, я могу проверить версию ios и установить соответствующую инициализацию nsurl, но это все еще остается проблемой. В объяснении отказа я прочитал:
В частности, мы обнаружили, что при запуске и / или загрузке контента ваше приложение хранит 7 Мб. Чтобы проверить, сколько данных хранит ваше приложение:
- Установите и запустите ваше приложение
- Выберите "Настройки"> "iCloud"> "Хранилище и резервное копирование"> "Управление хранилищем".
- При необходимости нажмите "Показать все приложения"
- Проверьте хранилище вашего приложения
Если я пытаюсь проверить это значение, я вижу 7 МБ также с правильной инициализацией nsurl (когда все атрибуты установлены правильно). Что такое правильное поведение? Кто-нибудь с этой проблемой? Нужно ли делать что-то конкретное перед проверкой хранилища приложений, предложенной Apple, чтобы сделать это значимым?
2 ответа
Я думаю, что хитрость заключается в том, чтобы добавить NSURLIsExcludedFromBackupKey и убедиться, что каталог находится за пределами каталога документов. Я сделал это, переместив свои документы в папку Library/Application Support (поскольку в папках /tmp или /Caches это не имело смысла):
// store in /Library/Application Support/BUNDLE_IDENTIFIER/Reference
// make sure Application Support folder exists
NSURL *applicationSupportDirectory = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:YES
error:&error];
if (error) {
NSLog(@"KCDM: Could not create application support directory. %@", error);
return nil;
}
NSURL *referenceFolder = [applicationSupportDirectory URLByAppendingPathComponent:@"Reference" isDirectory:YES];
if (![[NSFileManager defaultManager] createDirectoryAtPath:[referenceFolder path]
withIntermediateDirectories:YES
attributes:nil
error:&error]) {
NSLog(@"KCDM: Error creating Reference folder to store model %@: %@", modelName, error);
return nil;
}
BOOL success = [referenceFolder setResourceValue:@YES forKey: NSURLIsExcludedFromBackupKey error: &error];
if(!success){
NSLog(@"KCDM: Error excluding %@ from backup %@", referenceFolder, error);
}
У меня была та же проблема, что и у вас, пока я не удалил свое приложение со своего устройства и не переустановил. Мне также пришлось удалить существующие кэшированные данные из резервной копии iCloud, выбрав Настройки-> Хранение и резервное копирование -> Управление хранилищем
Это, казалось, сделало трюк. Кроме того, мой код для добавления атрибута пропуска немного отличается: код снят с этого поста
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);
if (&NSURLIsExcludedFromBackupKey == nil) { // iOS <= 5.0.1
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result == 0;
}
else { // iOS >= 5.1
NSError *error = nil;
[URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
return error == nil;
}
}