Thanks in advance for help.
I have excluded a folder from being backed up by iCloud but still it is backing up the files and when i visit iCould it is backed up. i use the following code to exclude the directory from being back up.
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
// 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;
}
and i call the above method as bellow
NSArray *Paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryDir = [Paths objectAtIndex:0];
NSString *downloadFolder = [libraryDir stringByAppendingPathComponent:#"downloads"];
NSError *error;
if (![[NSFileManager defaultManager] fileExistsAtPath:downloadFolder])
[[NSFileManager defaultManager] createDirectoryAtPath:downloadFolder withIntermediateDirectories:NO attributes:nil error:&error]; //Create folder
NSURL *documentURL = [NSURL URLWithString:downloadFolder];
[self addSkipBackupAttributeToItemAtURL:documentURL];
import this sys/xattr.h
- (BOOL) addSkipBackupAttributeToItemAtPath: (NSString *) path {
BOOL success = NO;
const char* filePath = [path fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
void* check = (void *)&NSURLIsExcludedFromBackupKey;
if (check != NULL) {
// 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 item at path %#", path);
}
}
NSURL *url = [NSURL fileURLWithPath: path];
success = [url setResourceValue: [NSNumber numberWithBool: YES] forKey: NSURLIsExcludedFromBackupKey error: nil];
} else {
// iOS 5.0.1 and lower
u_int8_t attrValue = 1;
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
success = (result == 0);
}
NSLog(#"Add skip backup attribute for item at path: %#, result: %d", path, success);
return success;
}
i hope this will work...
Related
I successfully test my in app purchase function and downloaded the content. However I am not sure of an right way to transfer it to Document folder. I tested with the code:
-(void)paymentQueue:(SKPaymentQueue *)queue updatedDownloads:(NSArray *)downloads
{
for (SKDownload *download in downloads)
{
switch (download.downloadState) {
case SKDownloadStateActive:
NSLog(#"Download progress = %f",
download.progress);
NSLog(#"Download time = %f",
download.timeRemaining);
break;
case SKDownloadStateFinished:
[self downloadFromURL:download.contentURL];///<--This is the function.
break;
}
}
}
-(void)downloadFromURL: (NSURL *) temporaryURL {
NSString *folderName = [[temporaryURL path] lastPathComponent];
NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *folder = [pathArr objectAtIndex:0];
NSString *filePath = [folder stringByAppendingPathComponent:folderName];
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
NSError *writeError = nil;
NSData *downloadData = [[NSData alloc] initWithContentsOfURL:temporaryURL];
[downloadData writeToURL: fileURL options:0 error:&writeError];
if( writeError) {
NSLog(#"Error in writing file %#' : \n %# ", filePath , writeError);
return;
}
NSLog(#"File successfully downloaded. Url is %#",fileURL.absoluteString);
//myFileURL = fileURL;
NSFileManager *filemgr;
NSArray *filelist;
int count;
int i;
filemgr =[NSFileManager defaultManager];
filelist = [filemgr contentsOfDirectoryAtPath:folder error:NULL];
count = [filelist count];
NSLog(#"file count %i",count);
for (i = 0; i < count; i++)
NSLog(#"%#", filelist[i]);
}
I get a #"File successfully downloaded. Url is %#" from the code above but NSLog(#"%#", filelist[i]); give me no content. What else is missing here? I found out about this link
but not sure how to incorporate into my code. Any pointer will be good.
Let's check:
-(void)downloadFromURL: (NSURL *) temporaryURL {
// at this time, file is downloaded successfully???
// I think you should check here
NSURL * temporaryURL;
NSFileManager *fm = [NSFileManager defaultManager];
BOOL existed = [fm fileExistsAtPath:temporaryURL.path];
if(existed) // file is existed
else // file is not existed == maybe download fails
}
My iOS application just got rejected because the application is storing data on Documents so it is backed up by iCloud, this is not allowed since the data is downloaded from a server.
But even though I'm using addSkipBackupAttributeToItemAtURL it still shows up as a backup to iCloud.Here the code which i have used
NSError *error = nil;
NSData *data = [NSData dataWithContentsOfURL:url options:0 error:&error];
if(!error)
{
[self HidePreLoader];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSLog(#"_paths--->%#",paths);
NSString *path = [paths objectAtIndex:0];
NSLog(#"_path---->%#",path);
NSString *dataPath = [path stringByAppendingPathComponent:#"/MyFolder"];
NSLog(#"_dataPath---->%#",dataPath);
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
{
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error];
}
NSString *zipPath = [dataPath stringByAppendingPathComponent:downfilename];
[data writeToFile:zipPath options:0 error:&error];
if(!error)
{
[self HidePreLoader];
ZipArchive *za = [[ZipArchive alloc] init];
if ([za UnzipOpenFile: zipPath]) {
BOOL ret = [za UnzipFileTo: dataPath overWrite: YES];
if (NO == ret){} [za UnzipCloseFile];
NSLog(#"folderPath--->%#",folderPath);
//Here i have used the use code
NSURL *guidesURL = [NSURL fileURLWithPath:folderPath];
[guidesURL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:NULL];
//The following code also doesnt work
//NSURL *guidesURL = [NSURL fileURLWithPath:folderPath];
//[self addSkipBackupAttributeToItemAtURL:guidesURL];
[self HidePreLoader];
NSString *path = nil;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
path = [folderPath stringByAppendingPathComponent:#"module-B1-ipadmain-swipe-tablet.html"];
}
else
{
path = [folderPath stringByAppendingPathComponent:#"module-B1-ipadmain-swipe-phone.html"];
}
NSLog(#"path--->%#",path);
dispatch_async(dispatch_get_main_queue(), ^{
appDel.currentReadingPlanWithPath = path;
appDel.moduleDownloaded = YES;
[appDel SetCurrentDownloadPath];
NSLog(#"file download success");
[progview setHidden:YES];
[progval setHidden:YES];
[self HidePreLoader];
downloadView.userInteractionEnabled=YES;
[self SetModuleDownloaded:#"true"];
[self ShowAlert:#"Download" message:#"Success"];
[self HidePreLoader];
});
[self HidePreLoader];
}
}
else
{
NSLog(#"Error saving file %#",error);
}
}
else
{
NSLog(#"Error downloading zip file: %#", error);
}
});
AddSkipBackupAttributeToItemAtURL method
-(BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
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;
}
When i try the above code.Still the iCloud shows the application in iOS7.Please help me to solve this issue.
Please check iOS version before using "addSkipBackupAttributeToItemAtURL" function.
Also follow this URL :
https://developer.apple.com/library/ios/qa/qa1719/_index.html
and this URL
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/PerformanceTuning/PerformanceTuning.html#//apple_ref/doc/uid/TP40007072-CH8-SW9
I have developed app in which i am downloading image from server and displaying in UITableView
App rejection reason
In particular, we found that on launch and/or content download, your app stores 2.67 MB. To check how much data your app is storing:
The iOS Data Storage Guidelines indicate that only content that the user creates using your app, e.g., documents, new files, edits, etc., should be backed up by iCloud.
Temporary files used by your app should only be stored in the /tmp directory; please remember to delete the files stored in this location when the user exits the app.
Data that can be recreated but must persist for proper functioning of your app - or because customers expect it to be available for offline use - should be marked with the "do not back up" attribute. For NSURL objects, add the NSURLIsExcludedFromBackupKey attribute to prevent the corresponding file from being backed up. For CFURLRef objects, use the corresponding kCFURLIsExcludedFromBackupKey attribute.
Here is my code shows how i am downloading data from server and displaying it:
- (BOOL)fileExist:(NSString *)name //Check's whether image Exists in Doc Dir.
{
BOOL theSuccess;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
NSFileManager *fileManager = [NSFileManager defaultManager];
theSuccess = [fileManager fileExistsAtPath:fullPath];
if(theSuccess){
return YES;
} else {
return NO;
}
}
- (void)downloadFile:(NSString *)urlFile withName:(NSString *)fileName //If image not exists it will download image.
{
NSString *trimmedString = [urlFile stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([trimmedString length]>0)
{
HTTPEaterResponse *response = [HTTPEater get:[NSString stringWithFormat:#"%#",trimmedString]];
if ([response isSuccessful])
{
[self saveImage:[[UIImage alloc] initWithData:[response body]] withName:fileName];
}
}
}
-(void)saveImage:(UIImage *)image withName:(NSString *)name //After downloading image it stores in Doc dir.
{
NSString *pngPath = [NSHomeDirectory() stringByAppendingPathComponent:[#"Documents/" stringByAppendingString:name]];
[UIImagePNGRepresentation(image) writeToFile:pngPath atomically:YES];
}
- (UIImage *)loadImage:(NSString *)name //Used for displaying.
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
UIImage *img = [UIImage imageWithContentsOfFile:fullPath];
return img;
}
Code for displaying data:
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
...
if ([dicImages valueForKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:#"merchantimage"]])
{
cell.MerchntLogo.image=[dicImages valueForKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:#"merchantimage"]];
}
else
{
if (!isDragging_msg && !isDecliring_msg)
{
if ([[[msg_array objectAtIndex:indexPath.row] valueForKey:#"merchantimage"] length]!=0)
{
[dicImages setObject:[UIImage imageNamed:#"rowDefault.png"] forKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:#"merchantimage"]];
[self performSelectorInBackground:#selector(downloadImage_3:) withObject:indexPath];
}
}
else
{
cell.MerchntLogo.image=[UIImage imageNamed:#"rowDefault.png"];
}
}
...
}
-(void)downloadImage_3:(NSIndexPath *)path{
if ([[[msg_array objectAtIndex:path.row] valueForKey:#"merchantimage"] length]!=0)
{
NSString *str=[[msg_array objectAtIndex:path.row] valueForKey:#"merchantimage"];
UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:str]]];
[dicImages setObject:img forKey:[[msg_array objectAtIndex:path.row] valueForKey:#"merchantimage"]];
[tblProdDetail performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
}
}
Please help me figure out why my app has been rejected, and what I can do to rectify the problem.
Your app is clearly violating Apple's Data storage guidelines which states that only user-generated data should be stored in the Documents folder. This data is automatically backed up to iCloud and goes against the 5GB cap. If an app stores too much data in this folder (as deemed by Apple), then it can be rejected from the App Store.
Your data wont classify as user generated content and it exceeds 2 MB which is the limit.
You can prevent the data from being backed up by referring here.
https://developer.apple.com/library/ios/qa/qa1719/_index.html
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
BOOL result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result;
}
You need to do what they a talking about. Mark files
Just add in didFinishLaunching
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
[self applyAttributes:documentsDirectory];
And then implements this methods
#pragma mark - Application's Documents directory
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
-(void)applyAttributes:(NSString *)folderPath
{
NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:folderPath error:nil];
NSEnumerator *filesEnumerator = [filesArray objectEnumerator];
NSString *fileName;
while (fileName = [filesEnumerator nextObject]) {
// NSLog(#"apply to %#", [[NSURL fileURLWithPath:[folderPath stringByAppendingPathComponent:fileName]] path]);
if([self addSkipBackupAttributeToItemAtURL:[NSURL fileURLWithPath:[folderPath stringByAppendingPathComponent:fileName]]])
{
//NSLog(#"success applying");
}
//NSDictionary *fileDictionary = [[NSFileManager defaultManager] attributesOfItemAtPath:[folderPath stringByAppendingPathComponent:fileName] error:nil];
//fileSize += [fileDictionary fileSize];
}
}
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
if([[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;
}
return NO;
}
Use this method to bypass storing data on iCloud
Pass file path to this method
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
BOOL result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result;
}
My application got rejected by Apple due to :
2.23: Apps must follow the iOS Data Storage Guidelines or they will be rejected
so is it possible that flag entire Document directory as do no backup ? my application runs in iOS 6.1 and higher .
I am familiar with this code , but I don't know hot to mark my Document directory with it
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
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;
}
EDITED :
Apple has told me that iCloud backups my photos from image gallery , I load images of gallery like this :
- (void)setupPageScroll {
NSString *imgCount;
int i;
[_scrollView setContentSize:CGSizeMake(_scrollView.frame.size.width * _pageControl.numberOfPages, _scrollView.frame.size.height)];
_scrollView.delegate = self;
for (i = 0 ; i < 10 ; i++) {
imgCount = [NSString stringWithFormat:#"%#%d.jpg",_gallName , i];
[self createPageWithImage:[UIImage imageNamed:imgCount] forPage:i];
}
}
- (void)createPageWithImage:(UIImage *)images forPage:(int)page
{
UIView *newView = [[UIView alloc] initWithFrame: CGRectMake(_scrollView.frame.size.width * page, 0, _scrollView.frame.size.width, _scrollView.frame.size.height)];
UIImageView *tempImage = [[UIImageView alloc]initWithImage:images];
[tempImage setContentMode:UIViewContentModeScaleAspectFit];
tempImage.frame = _galleryView.frame;
_imgGallery = tempImage;
[newView addSubview: _imgGallery];
[_scrollView addSubview: newView];
}
- (IBAction)pageChanged:(id)sender {
CGRect pageRect = CGRectMake(_pageControl.currentPage * _scrollView.frame.size.width, 0, _scrollView.frame.size.width, _scrollView.frame.size.height);
[_scrollView scrollRectToVisible: pageRect animated: YES];
}
How can skip these images ?
... And finally my application has been approved . just follow this instruction :
put this code on appDelegate.m (didFinishLunching)
NSString *docsDir;
NSArray *dirPaths;
NSURL * finalURL;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
finalURL = [NSURL fileURLWithPath:docsDir];
[self addSkipBackupAttributeToItemAtURL:finalURL];
and skip backup :
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
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;
}
You can mark as no-backup only the parent folder, not every file. But it should not be a Documents directory as it should contain only user-created content. You should use Library/Application Support (Technical Q&A QA1719)
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *directory = [paths objectAtIndex:0];
directory = [directory stringByAppendingPathComponent:#"MyData"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:directory] == NO) {
NSError *error;
if ([fileManager createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:&error] == NO) {
NSLog(#"Error: Unable to create directory: %#", error);
}
NSURL *url = [NSURL fileURLWithPath:directory];
// exclude downloads from iCloud backup
if ([url setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error] == NO) {
NSLog(#"Error: Unable to exclude directory from backup: %#", error);
}
}
Credits: xinsight blog
I am trying to download image files and store in NSDocumentDirectory. In order to do so, I has to turn off data backup on iCloud and iTunes. Below are my codes:
+(void)saveData:(NSData*)thedata:(NSString*)fileName
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *localFilePath = [documentsDirectory stringByAppendingPathComponent:fileName];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager createFileAtPath:localFilePath contents:thedata attributes:nil];
//prevent files from backup on iCloud or iTune
NSURL *fileURL = [NSURL URLWithString:localFilePath];
[self addSkipBackupAttributeToItemAtURL:fileURL];
}
and for my addskipbackupattributetoitematurl:
+(BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)fileURL
{
if (![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]])
{
NSLog(#"File %# doesn't exist!",[fileURL path]);
return NO;
}
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer isEqualToString:#"5.0.1"])
{
const char* filePath = [[fileURL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
NSLog(#"Excluded '%#' from backup",fileURL);
return result == 0;
}
else if (&NSURLIsExcludedFromBackupKey)
{
NSError *error = nil;
BOOL result = [fileURL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
if (result == NO)
{
NSLog(#"Error excluding '%#' from backup. Error: %#",fileURL, error);
return NO;
}
else
{
NSLog(#"Excluded '%#' from backup",fileURL);
return YES;
}
}
else
{
return YES;
}
}
However, the BOOL result = [fileURL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error]; created the following message
CFURLSetResourcePropertyForKey failed because it was passed this URL which has no scheme: /var/mobile/Applications/CF69D567-1D37-4053-BFA8-5D0FCBD9C2B2/Documents/coffee.jpg
I'm just wondering if any encountered this problem??
Solved. once I changed
NSURL *fileURL = [NSURL URLWithString:localFilePath];
to
NSURL *fileURL = [NSURL fileURLWithPath:localFilePath];
everything work perfectly.
Swift:
let fileURL = URL(fileURLWithPath: somepath)