Skip to content

Add option to configure Tracks to store its DB in Application Support instead of Documents#147

Merged
mokagio merged 9 commits intodevelopfrom
store-data-in-application-support
Oct 9, 2020
Merged

Add option to configure Tracks to store its DB in Application Support instead of Documents#147
mokagio merged 9 commits intodevelopfrom
store-data-in-application-support

Conversation

@mokagio
Copy link
Contributor

@mokagio mokagio commented Sep 23, 2020

See #146.

This is just a test to verify my internal non-sandboxed macOS app works fine when using Application Support.

Update: we decided to merge this change, but in a way that wouldn't change the behavior of Simplenote macOS.

To test these changes:

@mokagio mokagio force-pushed the store-data-in-application-support branch from 09c9afb to cedd0a5 Compare September 23, 2020 05:35
@mokagio mokagio marked this pull request as ready for review September 30, 2020 23:47
Copy link
Contributor Author

@mokagio mokagio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I refined the implementation to avoid changing the way existing consumers of the library store the DB.

@jleandroperez @jkmassel can I ask you for a new round of review?

Comment on lines +6 to +8
@property (nonnull, nonatomic, strong) NSManagedObjectContext *managedObjectContext;
@property (nonnull, nonatomic, strong) NSManagedObjectModel *managedObjectModel;
@property (nonnull, nonatomic, strong) NSPersistentStoreCoordinator *persistentStoreCoordinator;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to add the annotation here too to avoid warnings. It makes the diff a bit noisier but it's good to have it anyways.

The implementation of all those getters makes sure they are not nil, or rather, fails if they are, so nonnullable seemed appropriate.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup that's the perfect approach Gio!

/// the app is running and where to save the store.
///
/// The `super` `init` method defaults to `false` for backward compatibility.
- (nonnull instancetype)initWithSandboxedMode:(BOOL)sandboxed NS_DESIGNATED_INITIALIZER;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether the parameter should be an enum instead:

_ = TracksContextManager(storeLocation: .applicationSupport)
// or
_ = TracksContextManager(storeLocation: .documents)

I'm on the fence and might sit overnight. Regardless, because the changes doesn't affect existent consumers thanks to the init override below, I think it's okay to merge this as it is and then I can follow up with a refactor if we think it's worth it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be entirely honest, I would keep the initializer simple, and just switch to the Application Support folder.

Something in the lines of:

  • If a Documents folder already exists, use it
  • Otherwise, check if a folder in Applications Support exists, and use it
  • If none of the above, create a new folder in Applications Support

WYDT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with either approach. I like how pretty the enum is, but I like how much work @jleandroperez's isn't 😄


- (instancetype)initWithSandboxedMode:(BOOL)sandboxed {
self = [super init];
if (!self) { return nil; }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should never happen so I defined the initializer as nonnullable. In Swift land, that would be the case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Standard ObjC, exactly!

@mokagio mokagio changed the title Store Tracks.sqlite store in Application Support instead of Documents Add option to configure Tracks to store its DB in Application Support instead of Documents Oct 1, 2020
Copy link
Contributor

@jleandroperez jleandroperez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mokagio sir!! Few changes suggested:

  • Initializer fix (would prevent leaking memory)
  • ApplicationSupport API simplification (not required, not a blocker either!!)

As per the initializer detail, 10000% up to you!

  • Taking that parameter isn't a problem at all
  • It can be solved without specifying if we're sandboxed or not, as well. Yet another alternative, is to just always use the Application Support path, and migrate legacy databases, if needed

I would take the easiest path. As usual 😄

@implementation TracksContextManager

- (instancetype)init {
return [[TracksContextManager alloc] initWithSandboxedMode:true];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This initializer returning a new instance, rather than the one being initialized.

You would typically instantiate a Context Manager like this:

TracksContextManager *manager = [[TracksContextManager alloc] init];
  1. alloc reserves memory for the object
  2. init is expected to initialize the instance

In this case, init is alloc'ating more memory, and returning yet another instance.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this! Gosh 😳 I'm really rusty at writing Objective-C 🤦

I felt like there was something wrong with that, but it compiled and the tests passed so I shrugged it off.

Interestingly, Xcode also gives me a warning about it

image

It either came after I wrote the code and moved on or after I added the NS_DESIGNATED_INITIALIZER annotation. Regardless, I shouldn't have missed it... 😳

abort();
}

return applicationSupportURL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can proooobably simplify this API as follows:

NSURL *appSupportURL = [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask] lastObject];

Ref. here

(The Application Support path is expected to always be there!)

@mokagio
Copy link
Contributor Author

mokagio commented Oct 2, 2020

Thanks @jleandroperez for the great review!

Regarding the init, I like the idea of keeping it simple and eventually migrate everything to Application Support.

I haven't tried, but I think that even to just check whether a file exists in the Documents folder from a non-sandboxed app, macOS would request the user for permission. If that's the case, then we'd be back to square one, because the real aim of this change is avoid that behavior in non-sandboxed apps.

I really like the migration idea, but I think it needs more experimenting and might be best for a dedicated PR.

Copy link
Contributor

@jleandroperez jleandroperez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mokagio One tiny comment sent away (apologies I missed that!!).

Other than that, please :shipit: when ready!!

return [self applicationSupportURLForContainerApp];
} else {
return [self applicationDocumentsDirectory];
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mokagio Is it possible this logic is inverted? (sandboxed > Documents Directory?).

Otherwise non sandboxed apps would still trigger the Documents Folder alert perhaps?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are totally right!

I didn't notice because the tests were inverted, too 🤦‍♂️

@mokagio mokagio force-pushed the store-data-in-application-support branch from fcfec20 to aeb61db Compare October 5, 2020 04:19
@mokagio
Copy link
Contributor Author

mokagio commented Oct 5, 2020

😫 I feel like I'm in a deadlock... There's some inconsistent issue with the tests, which doesn't happen with the Xcode 12, but I can't upgrade to Xcode 12 because the pod validation fails.

Inconsistent as in this:

image

@mokagio mokagio force-pushed the store-data-in-application-support branch from aeb61db to 9eb9300 Compare October 8, 2020 05:47
@mokagio mokagio force-pushed the store-data-in-application-support branch from 9eb9300 to a074e1f Compare October 8, 2020 08:34
@mokagio mokagio force-pushed the store-data-in-application-support branch from a074e1f to 61a05f6 Compare October 8, 2020 08:43
This will allow us to add the conditional logic for the sandbox vs
non-sandbox location later on.
We'll need this later to make the custom init with the sandbox mode flag
non-nullable.
This should have always been the case, but somehow I got confused and
didn't realize my mistake.

Thanks @jleandroperez for picking this up! Goes to show that tests are
only good when written properly!

https://github.com/Automattic/Automattic-Tracks-iOS/pull/147/files/3e38df8087e7b38a76b45acc5e89527746b4145b#r498830462
@mokagio mokagio force-pushed the store-data-in-application-support branch from 61a05f6 to 9d50fde Compare October 9, 2020 00:36
Copy link
Contributor

@jleandroperez jleandroperez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit: sir!!

@jleandroperez
Copy link
Contributor

For the record, Cocoapods had issues finding the Sodium-Fork framework. Workaround involved running bundle exec pod repo update

Thank you Gio!!

@mokagio mokagio merged commit 6cf038e into develop Oct 9, 2020
@mokagio mokagio deleted the store-data-in-application-support branch October 9, 2020 01:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants