Realm-cocoa: Default realm location breaks Apple review rules

Created on 5 Oct 2016  路  32Comments  路  Source: realm/realm-cocoa

Goals

Pass the Apple review with an App using Realm.io

Expected Results

Review failed.

Your app has the UIFileSharingEnabled key set to true in the info.plist, but the Documents folder includes files and folders not intended for file sharing.

The thing I'm seeing is:

image

So I guess they don't like it. While it's nice to have this for debugging and maybe exporting to you Mac and looking through the database with an external tool, I think the default should be safe for the Apple Store submission.

Actual Results

Maybe we should make a default location be somewhere else, since I suspect more people may forget to change the location.

Steps to Reproduce

Just enable file sharing with iTunes by setting UIFileSharingEnabled and you'll see the problem.

Code Sample

.

Version of Realm and Tooling

In the CONTRIBUTING guidelines, you will find a script,
which will help determining these versions.

Realm version: Realm 1.0.2

Xcode version: Xcode 8

iOS/OSX version: iOS 10 / El Captain

Dependency manager + version: pod

Linked issues

3238

T-Help faq

Most helpful comment

Bingo. That's the issue. I have Realm migration handling code run early in the app startup, and it was initialising the Realm files 1st time. Now I've fixed it, and it seems like our code works!

I have:

RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *appSupportDirPath = [paths firstObject];
NSString *realmPath = [appSupportDirPath stringByAppendingPathComponent:@"default.realm"];
config.fileURL = [NSURL fileURLWithPath:realmPath];
[RLMRealmConfiguration setDefaultConfiguration:config];

image

Realm files are gone. The BZip'ed JSON files are my data files.

Should we put a note in Realm guide on default location of the database being in conflict with UIFileSharingEnabled ?

All 32 comments

Just tried changing the path (below), but it didn't work. 4 files of Realm are still created:

RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory,, NSUserDomainMask, YES);
NSString *appSupportDirPath = [paths firstObject];
NSString *realmPath = [appSupportDirPath stringByAppendingPathComponent:@"default.realm"];
configuration.fileURL = [NSURL fileURLWithPath:realmPath];
[RLMRealmConfiguration setDefaultConfiguration:configuration];
NSLog(@"XXXX path=%@ realmURL: '%@'", realmPath, configuration.fileURL);

Hi @wkoszek, you're right that we should be opting out those files from backups, but moving them to a separate location isn't the right way to resolve this IMO. Instead, we should be setting the appropriate NSFileProtection attributes to prevent those files from being included in iTunes or iCloud backups and file transfers.

Until we get around to doing this, you can do that explicitly in your apps.

NSFileProtection is about encryption, so doesn't seem relevant here. You may be thinking of NSURLIsExcludedFromBackupKey which will prevent a given file from being backed up. I don't think that has any impact on the iTunes file sharing UI though.

We cannot change the default path of Realm files without breaking all existing apps that are using the default path. The only solution here, IMO, is for anyone that wants their app to store Realm files in different location, for whatever reason, to specify a different path in their configuration.

Yes, sorry for the mixup, I was thinking of NSURLIsExcludedFromBackupKey.

@jpsim @bdash Ok, so I gave you an example on how I wanted to deal with the issue, but it didn't seem to work for me. What's the proper way to change the directory for Realm files?

I don't like the new title of this issue. It's doesn't reflect my problem enough :-)

I don't like the new title of this issue. It's doesn't reflect my problem enough :-)

I apologize, I've conflated your issue with a different issue you made me realize we have. I'll open a new issue for that one.

@jpsim No worries man.

Created #4189 for the other issue.

To answer your other question:

What's the proper way to change the directory for Realm files?

You can specify the location of Realm files by setting the fileURL property of its RLMRealmConfiguration:

RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
config.fileURL = [NSURL URLWithString:@"/path/to/file.realm"];
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];

@jpsim So can you confirm that an inability of doing:

<what you did and I've done before>
[RLMRealmConfiguration setDefaultConfiguration:configuration];

is a bug too? I'd expect that this default config will kick in each time I do:

RLMRealm *realm = [RLMRealm defaultRealm];

At least that's what I do in my data model right now.

I don't understand your last comment.

4 files of Realm are still created:

Yes, that's expected. No matter the root directory of the realm file, the auxiliary files will always be created, and they will always be located next to the main file.

I had opened an issue a long time ago to allow specifying a custom location for the auxiliary realm files, but that was closed due to not solving any issue we were aware of: realm/realm-core#911

Sounds like this would require the same solution, but for a different problem.

Unless there's a different solution to this that I'm not aware of.

Does that sound right to you @wkoszek?

From Apple's Review feedback it looks like I need to get rid of all files from the iTunes shared directory, if I want to have this file sharing functionality enabled. Rephrasing: if I open my app in iTunes and look into shared dir, Realm files can't be there.

I'm looking for a way to do it.

Note 1 my hope was that by relocating the .realm file all other files (.lock, .management, .note) will also be placed in a different file. I think you're admitting there's no way to do it currently?

Can you confirm if I got that right?

Note 1 my hope was that by relocating the .realm file all other files (.lock, .management, .note) will also be placed in a different file. I think you're admitting there's no way to do it currently?

Yes, that's correct, those files are always created when opening a Realm, unless the Realm is only ever opened with RLMRealmConfiguration.readOnly set to YES.

Those files are necessary to ensure safe inter-process access to the Realm. Which is why I think the only solution is to allow developers (you) to override the location of the auxiliary files, as to not have them next to the main .realm file in order to satisfy Apple's requirements regarding iTunes file sharing.

That's a bummer. Here's the "spec" how I want it to work:

I pass /path/to/dir and I get realm.default, realm.default.lock, realm.default.management and realm.default.note created in there.

Trying to think what my workaround can be. Going to try your code snippet:

RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
config.fileURL = [NSURL URLWithString:@"/path/to/file.realm"];
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];

now that I'm at home

Again, confused by your last comment. As far as I know, the way to expose this would be:

RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
config.fileURL = [NSURL URLWithString:@"/path/to/realm/file.realm"];
config.supportingFilesRootURL = [NSURL URLWithString:@"/dir/for/aux/files/"];
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];

So that your /path/to/realm directory would be "pristine", just have the realm file(s), so that iTunes/Apple would be happy, while making sure the important auxiliary files are still available to Realm.

Not sure what you're confused about. I'm looking for a way to get rid of these 4 files from the iTunes shared dir. That's all I want :-)

Like I said earlier, those files are always created when opening a Realm, unless the Realm is only ever opened in read-only mode (i.e. RLMRealmConfiguration.readOnly set to YES).

They're also always created in the same directory as the main realm file, but it would be possible to support specifying a custom location for these files, as we've already considered in realm/realm-core#911, but subsequently closed.

Ok. I think your confusion comes from distinguishing .realm files from .lock etc. files. I don't distinguish that. I don't care -- to me these 4 files go together as "Realm database". I don't know which of these Apple doesn't like, so I just want all 4 of them to disappear from a shared folder.

Now I gave you the snippet which I showed. It didn't work for me.

So now I'm using yours:

- (RLMRealm *) privDataStore {
    RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
    config.fileURL = [NSURL fileURLWithPath:@"/tmp/s.realm"];
    [RLMRealmConfiguration setDefaultConfiguration:config]; // just in case
    return [RLMRealm realmWithConfiguration:config error:nil];
}

(I've changed the URLWithString:@"/path/to/file.realm" to fileURLWithPath).

It doesn't seem to work. The files are sill visible in iTunes as if fileURL was getting ignored.

Reading Realm source code now...

If you've opened the Realm prior to setting this file URL in the configuration, then the files from the previous access will still exist.

Bingo. That's the issue. I have Realm migration handling code run early in the app startup, and it was initialising the Realm files 1st time. Now I've fixed it, and it seems like our code works!

I have:

RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *appSupportDirPath = [paths firstObject];
NSString *realmPath = [appSupportDirPath stringByAppendingPathComponent:@"default.realm"];
config.fileURL = [NSURL fileURLWithPath:realmPath];
[RLMRealmConfiguration setDefaultConfiguration:config];

image

Realm files are gone. The BZip'ed JSON files are my data files.

Should we put a note in Realm guide on default location of the database being in conflict with UIFileSharingEnabled ?

Can you instead just hide the file(s) you don't want to display in iTunes using NSURLIsHiddenKey?

Unfortunately, iTunes appears to ignore NSURLIsHiddenKey, and setting a file as hidden using chflags("path", UF_HIDDEN) also doesn't have any effect.

@jpsim Should we document somehow that UIFileSharingEnabled collides with default Realm settings ?

Since that's true of anything stored in Documents, and not unique to Realm, I don't think it warrants a mention in the docs. This is the first time anyone's ever brought this to our attention, so I doubt this is a common occurrence.

Ok. Maybe the UIFileSharingEnabled isn't as popular as I expected.

Well, this thread has certainly saved me some precious time. Not a common occurrence, but it surely does clash with built-in functionality of UIFileSharingEnabled, so I suppose a paragraph in docs wouldn't hurt either.

By default Realm should not be creating the database in the Documents directory, and if it does and needs to be backed up then use a subfolder called 'realm' in the Documents directory. The contents of which would not be visible to the user unless they copied the folder from iTunes. The correct default folder is "Library/Application Support" - well that is what Apple's Core Data defaults to.

I'm using RealmSwift, I'm trying to change default place for saving/creating realm files from Documents to Library/Application Support, works fine, but Realm continue create files in Documents directory too, and I have to remove it manually, is this issue, or I'm doing something wrong?

var realmConfig = Realm.Configuration.defaultConfiguration
        let paths = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory,
                                                        .userDomainMask,
                                                        true)
        let applicationSupportDirectoryPath = paths.first
        if let applicationSupportDirectoryPath = applicationSupportDirectoryPath {
            let  realmPath = applicationSupportDirectoryPath.appending("/default.realm")
            realmConfig.fileURL = URL(fileURLWithPath: realmPath)
            Realm.Configuration.defaultConfiguration = realmConfig
        }

i am getting crash like 'A Subscription can only be created in a Query-based Realm.'

Thanks in advanced.

This is a really big problem.I have trashed a lot of time because of this thing and the problem is still not resolved.I think it would be appropriate to do something in the next updates...

@sergstav did you find any solution? I am getting same error..

@invisible66 yes, I have a solution that allows me to pass review.
I use this code
Screenshot 2019-12-04 at 14 32 49

@sergstav Thank you so much. You saved my day :)

Was this page helpful?
0 / 5 - 0 ratings