从iCloud备份中排除:NSURLIsExcludedFromBackupKey

我的应用程序已被拒绝第二次,我失去了3个星期:(

第一次提交,我排除了只有董事在iCloud备份。 苹果拒绝…

第二次提交时,我排除了从iCloud备份下载的“DIRECTORIES&PICTURES”。 苹果再次拒绝…苹果也抱怨说,我没有“恢复”function,我的应用程序内购买,而事实上,我有一个“恢复”button,它在我testing它的时候工作。

我已经完成了苹果通过使用NSURLIsExcludedFromBackupKey排除文件备份的build议。 有一个有趣的评论由Macmade的在这里stackoverflow :

有时候苹果的评论家认为你的数据可以重新生成,而不是。 那么你将不得不解释为什么要备份数据

审阅者多久会被误解,我们必须向他们解释,该内容是否需要离线和不可重新生成?

这里是我用来从iCloud中排除我的文件和目录的代码。 你发现任何问题?

- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL { // There's a chance the download failed, but don't assert here //assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]); NSError *error = nil; BOOL success = [URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error: &error]; if(!success){ NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error); } return success; } //Download picture from Google and exclude it from being backed-up in iCloud - (void)downloadFetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *)error { if (error == nil) { // successfully retrieved this photo's data; save it to disk GDataEntryPhoto *photoEntry = [fetcher propertyForKey:@"photo entry"]; // Create album directory if it doesn't already exist NSString *path = [self findOrCreateApplicationSupportSubPath:[photoEntry albumTitle]]; path = [path stringByAppendingPathComponent:[[photoEntry title] stringValue]]; if (path != nil) { // Write to disk BOOL didSave = [data writeToFile:path options:NSDataWritingAtomic error:&error]; if (didSave) { // Exclude file from being backed up in iCloud NSURL *url = [NSURL fileURLWithPath:path]; BOOL excludeBackupResult = [self addSkipBackupAttributeToItemAtURL:url]; if (excludeBackupResult == NO) { NSLog(@"Error excluding FILE from iCloud: %@", path); } // Update the download progress bar _downloadedFileCounter = _downloadedFileCounter + 1; float progress = _downloadedFileCounter / kMaleWireframeImagesTotal; [self updateProgress:progress]; // The download completed. -2 just incase a package is lost, but let the user move on... if (_downloadedFileCounter >= _downloadableFilesTotal -2) { [_panel6 downloadCompleted]; } } else { // error saving file. Perhaps out of space? Write permissions error? NSLog(@"Save anatomy picture failed: %@", error.localizedDescription); } } else { NSLog(@"downloadFetcher: Cannot create directory"); } } else { NSLog(@"downloadFetcher failed: %@", error); } } //Create directory and exclude it from being backed-up in iCloud -(NSString*)findOrCreateApplicationSupportSubPath:(NSString*)subPath { NSString *resolvedPath; NSArray *appSupportDir = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); if ([appSupportDir count] != 0) { resolvedPath = [appSupportDir objectAtIndex:0]; // Append the name of this application NSString *executableName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleExecutable"]; resolvedPath = [resolvedPath stringByAppendingPathComponent:executableName]; resolvedPath = [resolvedPath stringByAppendingPathComponent:subPath]; NSFileManager *manager = [NSFileManager defaultManager]; if (![manager fileExistsAtPath:resolvedPath]) { // Path doesn't exist, creates it NSError *error; BOOL successful = [manager createDirectoryAtPath:resolvedPath withIntermediateDirectories:YES attributes:nil error:&error]; if(!successful) { NSLog(@"ERROR creating APP Support Sub-Directory: %@", error.localizedDescription); return nil; } else { // Exclude path from backing-up in iCloud NSURL *url = [NSURL fileURLWithPath:resolvedPath]; BOOL excludeBackupResult = [self addSkipBackupAttributeToItemAtURL:url]; if(!excludeBackupResult){ NSLog(@"Error excluding DIRECTORY from iCloud backup. This is a violation to their guideline."); return nil; } } } } else { NSLog(@"No Application Support Path available"); return nil; } return resolvedPath; } 

我想诀窍是添加NSURLIsExcludedFromBackupKey或确保目录是在文档目录之外。 我通过将文档移动到Library / Application Support文件夹(因为它在/ tmp或/ Caches文件夹中没有意义):

 - (void)createNewRefFolder { NSError *error; // 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); } 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: %@ ...", error); } BOOL success = [referenceFolder setResourceValue:@YES forKey: NSURLIsExcludedFromBackupKey error: &error]; if(!success){ NSLog(@"KCDM: Error excluding %@ from backup %@", referenceFolder, error); } } 

从以前的答案很less更新。

你必须检查文件的存在。 否则,你会得到这个错误,

 Error excluding [FileName] from backup: Error Domain=NSCocoaErrorDomain Code=4 "The file “[FileName]” doesn't exist." ... 

我不确定是否应该检查值是否已经更新。 例如,如果API重置已经设定值或不。 如果它试图再次更新文件系统的设置值,更费时,我想。

更新的方法…

 + (BOOL)addSkipBackupAttributeToURLAtPath:(NSURL *)url { if (!url) return NO; if (![[NSFileManager defaultManager] fileExistsAtPath:url.path]) return NO; NSError *error = nil; NSNumber *value = nil; BOOL success = [url getResourceValue:&value forKey:NSURLIsExcludedFromBackupKey error:&error]; if (value.boolValue == YES) return YES; success = [url setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error]; if(!success){ NSLog(@"Error excluding %@ from backup: %@", [url lastPathComponent], error); } return success; } + (BOOL)addSkipBackupAttributeToFileAtPath:(NSString *)path { if (!path) return NO; return [self addSkipBackupAttributeToURLAtPath:[NSURL fileURLWithPath:path]]; }