Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iPhone App Rejected because of iCloud Data Storage Guidelines

A critical bugfix update to one of my apps was recently rejected due to an alleged violation of the iCloud Data Storage Guidelines.

Here's how my app stores data (hasn't been a problem since the first version of my app was approved in 2009):

  1. On startup, it copies a "starter" SQLite3 database from the app bundle to the Documents folder.
  2. The database contains the basic schema and some example data so the user can see how to use the app. It's small - just under 3MB.
  3. The user's future work is then saved only in this database file. They may delete or keep the samples, they may add tons of their own data, but that database file will always be there.

An update earlier this year was rejected for the same reason, but when I gave them the explanation above, the app status changed from "Rejected" to "In Review" to "Processing for App Store." They didn't send me any explanation, so I thought it was just a misunderstanding on the reviewer's part.

This time, the reviewer responded to my explanation by simply saying that non-user-generated data shouldn't be stored in iCloud and my update remains in the "Rejected" state.

But I don't understand what I'm supposed to do here. Because all of the user's work is kept in the database, it's not an option for me to exclude this from iCloud backup or store it in a Cache folder. Also, I can't really cleanly separate "user-generated" from "non-user-generated" data because the app works from the same database file. The initial, non-user-generated data will be quickly replaced with the user's own data, though the filename and directory location of the database will remain the same.

And even if there were no sample data in the database, any database-backed app will still have to generate an empty database when it starts - even if the only thing it holds is the app's database schema.

This must be a very common problem, but unfortunately it's not okay for me to just turn off backup - users put a lot of work into the data they store in my app, and iCloud backup is very important to them.

What options do I have at this point? Here's what I can see:

  1. Contact Apple again and try to explain what's going on.

  2. Can I set the file's backup attribute to NO and then only toggle it to YES when the user makes their first change? Is that okay technically and okay with Apple?

  3. Remove my example data from the database. This will be really bad for usability and will increase my support load, but I'm willing to do it if it will get my update approved. However, I'll still have to create a stub database at startup to hold the empty database schema, so I'm not sure if that will even make a difference in the approval process.

  4. Cry.

Anyone have any advice? I have to imagine that there are lots of other apps that use a database the same way mine does, but don't have the option of just disabling backup.

It's also very depressing that any changes I make will require another round of testing and app review, which will set back my critical update an additional 2 - 3 weeks. :/

UPDATE: There may be another option: can I simply save the file in Library/ instead of Documents/, since their problem seems to be specifically with the use of the Documents folder? Will the file be backed up if it's stored in Library/?

UPDATE 2: The thing I find most confusing is that any database-backed app (even if it uses Core Data, I assume) will have to create a database file containing at least the app's schema. Is the problem just that the size of my database is too big? Because I can't see how any database-backed application can avoid having to create a database at startup.

UPDATE 3: I'm using a custom SQLite interaction layer - not Core Data. Also, the example data consists of starter images, which the user will probably end up deleting as they start using the app.

like image 416
Bill Avatar asked Jul 07 '12 12:07

Bill


People also ask

Why does my iPhone say there is not enough iCloud storage when there is?

This error message is pointing to lack of storage space in your iCloud Account and has nothing to do with lack of native storage space on your iPhone. Hence, the only way to fix “Not Enough iCloud Storage” error on iPhone or iPad is to free up storage space in your iCloud Account or buy additional iCloud Storage Space.

Why does Apple keep rejecting my app?

Lack of app description, metadata, screenshots, and preview could possibly be the reason behind app declination. The incorrect information about the application can also cause App Store rejection. Try to keep your description to the point and accurate. Also, make sure your app doesn't point out any lies.

How do I get rid of not enough iCloud storage?

Go to Settings > General > Storage & iCloud Usage, and tap Manage Storage under the iCloud section. If there are any device(s) you no longer own or use listed there, tap 'em and click "Delete Backup." There's no reason to let whatever crap was on your iPhone 4 hog up your precious 5GB of free iCloud space.

How do I get my apps to use iCloud storage?

When you first set up iCloud on a device, iCloud storage is automatically turned on for certain apps. Some iCloud features are also turned on automatically. You can turn these on or off at any time and customize the settings for each device. See Set up iCloud on all your devices.


3 Answers

3MB seems like quite a lot of sample data stored in a database. If you pull out the images and store references to the images in the database instead you should be able to get this usage down a lot. You can then change your database's image getter code to something like this:

- (UIImage *)image
{
    NSString *imageName = self.imageName;
    UIImage *image = [UIImage imageNamed:imageName];
    if (!image)
    {
        NSString *imageLibraryPath = ...;
        image = [UIImage imageWithPath:[imageLibraryPath stringByAddingPathComponent:imageName]];
    }
    return image;
}

- (void)setImage:(UIImage *)image
{
    [self setImageData:UIImagePNGRepresentation(image)];
}

- (void)setImageData:(NSData *)imageData
{
    NSString *imageLibraryPath = ...;
    NSString *fileName = self.uniqueId; //or something else, UUID maybe?
    NSString *filePath = [imageLibraryPath stringByAddingPathComponent:imageName];
    [imageData writeToFile:filePath atomically:YES]; // maybe dispatch_async this into the background?
    self.fileName = fileName;
}

The self.fileName would be backed by your database.

By reducing your data storage in this way you should be able to get approved as you are not storing relatively large amounts of data on the phone. The images can also be in the app bundle this way and do not need to duplicated at all.

like image 82
hypercrypt Avatar answered Sep 21 '22 04:09

hypercrypt


I have a really stupid idea. But maybe it is valid.

You can show a popup on startup asking "Would you like me to create some demo data". When the user clicks "Yes", its user generated data.

like image 24
Tomen Avatar answered Sep 20 '22 04:09

Tomen


One work around would be to read the SQL file out of the bundle until the user tries to edit something. Then copy it over. Since the file is small it should not even require a spinner.

I had this exact problem with an App recently. In our case we we using core data and copied the SQL file on startup as well.

Unfortunately you have to target iOS 5.

https://developer.apple.com/library/ios/qa/qa1719/_index.html

like image 45
logancautrell Avatar answered Sep 24 '22 04:09

logancautrell