iCloud和Core Data预填充数据库

col*_*ron 11 core-data ios icloud

我有一个带有预先填充的.sqlite文件的应用程序,该文件在首次打开应用程序时被复制到用户的Documents目录中.这个文件是12.9MB.现在两次,我的应用程序因为拒绝备注将目标更改为iOS5而被拒绝:

二进制被拒绝2012年4月24日上午10:12

拒绝的理由:

2.23应用必须遵循iOS数据存储指南,否则将被拒绝

2012年4月24日上午10:12 来自Apple.

2.23

我们发现您的应用不符合iOS数据存储指南,这是根据App Store审核指南所要求的.

特别是,我们发现在内容下载时,您的应用程序存储了12.81 MB.要检查应用存储的数据量:

  • 安装并启动您的应用
  • 转至设置> iCloud>存储和备份>管理存储
  • 如有必要,请点按"显示所有应用"
  • 检查您应用的存储空间

iOS数据存储指南指出,只有用户使用您的应用创建的内容(例如,文档,新文件,编辑等)可以存储在/ Documents目录中 - 并由iCloud备份.

应用程序使用的临时文件只应存储在/ tmp目录中; 请记得在用户退出应用程序时删除存储在此位置的文件.

可以重新创建但必须保持应用程序正常运行的数据 - 或者因为客户希望它可供脱机使用 - 应标记为"不备份"属性.对于NSURL对象,请添加NSURLIsExcludedFromBackupKey属性以防止备份相应的文件.对于CFURLRef对象,请使用相应的kCFURLIsExcludedFromBackupKey属性.

有关详细信息,请参阅技术问答1719:如何防止文件备份到iCloud和iTunes?.

有必要修改您的应用程序以满足iOS数据存储指南的要求.

我已尝试按照"数据存储指南"中的建议设置"不备份"属性,但又被拒绝了.

我不在我的应用程序中使用iCloud,而设置> iCloud>等根本没有显示任何用法.

我无法使用Cachestmp目录,因为用户在创建后修改了数据库.

我似乎介于摇滚和硬地之间,Apple不允许这种应用程序运行.

有没有人遇到过这个问题并设法克服它?

编辑17-5-12 我还没有设法让这个应用程序获得批准.有没有人设法做到这一点?

编辑1-7-12 由于同样的原因,我的应用程序再次被拒绝.我不知道该怎么做,当然这是一个常见的使用场景.

编辑11-9-12 应用程序现已批准 - 请参阅下面的解决方案.我希望它可以帮助别人.

col*_*ron 9

好的,这是我设法获得批准的解决方案(最后!)

这是用于设置"跳过备份"属性的代码 - 请注意,对于5.0.1及更低版本以及5.1及更高版本,它是不同的.

#include <sys/xattr.h>
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
    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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的 persistentStoreCoordinator

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    if (__persistentStoreCoordinator != nil)
    {
        return __persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"store.sqlite"];

    NSError *error;

    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *storePath = [[[self applicationDocumentsDirectory] path] stringByAppendingPathComponent:@"store.sqlite"];

    // For iOS 5.0 - store in Caches and just put up with purging
    // Users should be on at least 5.0.1 anyway
    if ([[[UIDevice currentDevice] systemVersion] isEqualToString:@"5.0"]) {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        NSString *cacheDirectory = [paths objectAtIndex:0];
        NSString *oldStorePath = [storePath copy];
        storePath = [cacheDirectory stringByAppendingPathComponent:@"store.sqlite"];
        storeURL = [NSURL URLWithString:storePath];

        // Copy existing file
        if ([fileManager fileExistsAtPath:oldStorePath]) {
            [fileManager copyItemAtPath:oldStorePath toPath:storePath error:NULL];
            [fileManager removeItemAtPath:oldStorePath error:NULL];
        }
    }
    // END iOS 5.0

    if (![fileManager fileExistsAtPath:storePath]) {
        // File doesn't exist - copy it over
        NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"store" ofType:@"sqlite"];
        if (defaultStorePath) {
            [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
        }
    }

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    [self addSkipBackupAttributeToItemAtURL:storeURL];

    return __persistentStoreCoordinator;
}
Run Code Online (Sandbox Code Playgroud)

请注意,我决定只Caches为iOS 5.0用户存储并忍受清除.

本月苹果批准了这一点.

请不要复制并粘贴此代码而不首先阅读和理解它 - 它可能不完全准确或优化,但我希望它可以引导某人找到帮助他们的解决方案.