【问题标题】:Exclude from iCloud backup: NSURLIsExcludedFromBackupKey从 iCloud 备份中排除:NSURLIsExcludedFromBackupKey
【发布时间】:2014-10-20 11:13:22
【问题描述】:

我的应用第二次被拒绝,我损失了 3 周 :(

第一次提交时,我只排除了在 iCloud 中备份的目录。苹果拒绝了...

第二次提交时,我将下载的 DIRECTORIES & PICTURES 排除在 iCloud 中备份。 Apple 再次拒绝... Apple 还抱怨我的应用内购买没有“恢复”功能,而事实上,我确实有一个“恢复”按钮,并且在我测试时它有效。

我已经按照 Apple 的建议通过使用 NSURLIsExcludedFromBackupKey 将文件排除在备份之外来完成。 Macmade's 在stackoverflow here 上发表了一条有趣的评论:

有时,Apple 审核人员认为您的数据可以重新生成,当 它不是。然后你必须解释为什么必须备份数据

审稿人多久误解一次,我们必须向他们解释内容需要离线且不可重新生成?

这是我用来从 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;
}

【问题讨论】:

    标签: ios icloud


    【解决方案1】:

    我认为诀窍是添加 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);
        }
    }
    

    【讨论】:

    • 这个答案很好。我刚刚为任何想要在他们的项目中直接复制和粘贴此代码的人更新了它
    • 为 NSURLIsExcludedFromBackupKey 设置 false 对于文档目录中的文件也足够了 source
    • 据此,应用程序支持文件夹包含在 iCloud 备份中developer.apple.com/library/content/documentation/…
    【解决方案2】:

    从以前的答案中更新一点。

    您必须检查文件是否存在。否则会报这个错误,

    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]];
    }
    

    【讨论】:

      猜你喜欢
      • 2012-08-19
      • 1970-01-01
      • 2015-01-14
      • 2012-10-12
      • 2015-01-24
      • 1970-01-01
      • 2013-02-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多