Krunal
Krunal

Reputation: 6490

App rejected due to downloading of image from server iOS

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.

Upvotes: 3

Views: 1146

Answers (3)

Xcoder
Xcoder

Reputation: 1807

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

Upvotes: 3

Chamira Fernando
Chamira Fernando

Reputation: 6846

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

Upvotes: 1

nerowolfe
nerowolfe

Reputation: 4817

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;

}

Upvotes: 2

Related Questions