My application just rejected because I copied sqlite database in NSDocumentDirectory and didn't exclude it from being synced to iCloud. I tried to add code to exclude it from iCloud but it is still occupying same space in iCloud. Here is my code.
- (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;
}
}
+ (void)copyDatabaseIfNeeded {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
NSString *toPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:toPath];
if(!success) {
NSString *fromPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
NSURL *toURL = [NSURL fileURLWithPath:toPath];
NSURL *fromURL = [NSURL fileURLWithPath:fromPath];
[[NSFileManager defaultManager] addSkipBackupAttributeToItemAtURL:toURL];
[[NSFileManager defaultManager] addSkipBackupAttributeToItemAtURL:fromURL];
success = [fileManager copyItemAtURL:fromURL toURL:toURL error:&error];
if (!success)
NSLog(@"Failed to create writable database file with message '%@'.", [error localizedDescription]);
}
}
+ (NSString *)getDBPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:databaseName];
}
Please help.
You set the skip back attribute to the file before coping it, since the file is not yet copied there the filemanager can't change the properties of that file:
Also you are not calling the addSkipBackupAttributeToItemAtURL:
on self but on NSFileManager
which does have this method declared.
You can addSkipBackupAttributeToItemAtURL:
from a class method if you declared it as an instance methods, change it to +
to make it a class method.
Change it to something like:
+ (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;
}
}
+ (void)copyDatabaseIfNeeded {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
NSString *toPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:toPath];
if(!success) {
NSString *fromPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
NSURL *toURL = [NSURL fileURLWithPath:toPath];
NSURL *fromURL = [NSURL fileURLWithPath:fromPath];
success = [fileManager copyItemAtURL:fromURL toURL:toURL error:&error];
if (success) {
[self addSkipBackupAttributeToItemAtURL:toURL];
} else {
NSLog(@"Failed to create writable database file with message '%@'.", [error localizedDescription]);
}
}
}
Also a my comment stated I removed the [[NSFileManager defaultManager] addSkipBackupAttributeToItemAtURL:fromURL];
since that file will a not be included in an iCloud backup and b files in the bundle are readonly and can't there for be modified.