7
votes

I created a WatchKit Application with the default XCode Template. I added an app group entitlement to the iOS Target, to the Watchkit App Target and to the Watchkit App Extension Target. (this is the app group name: group.com.lombax.fiveminutes) Then, I tried to access the shared folder URL with both the iOS App and the WatchKit Extension:

Extension:

@implementation ExtensionDelegate

- (void)applicationDidFinishLaunching {
    // Perform any final initialization of your application.
    NSURL *test = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.lombax.fiveminutes"];
}

iOS App:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.

    NSURL *test = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.lombax.fiveminutes"];
// ... 
}

However, the test NSURL is different:

On iOS:

file:///Users/Lombardo/Library/Developer/CoreSimulator/Devices/38B983DB-342F-4A47-8C26-5D2C92CDB666/data/Containers/Shared/AppGroup/8DEE182E-AFE6-47DD-BA2B-6B0520158A8B/

on Watch:

file:///Users/Lombardo/Library/Developer/CoreSimulator/Devices/BF52D613-25FF-4092-A5B2-9C3F1B616160/data/Containers/Shared/AppGroup/CECB5EFC-7FBD-4C84-A878-1314CB7CF211/

And for this reason I'm unable to share data between the iOS App and the WatchKit Extension.

I cannon try on a real device since I don't have WatchOS 2.0 on my Apple Watch. Any advice? Thanks

UPDATE I did some other tests:

  • Installed WatchOS 2, the issue still persists on real devices.

This is the store url for my iPhone:

NSURL * @"file:///private/var/mobile/Containers/Shared/AppGroup/3D05D159-94D6-409C-9A38-90E0830D0C3F/FiveMinutes.sqlite"

And this is the store url for my Watch:

NSURL * @"file:///private/var/mobile/Containers/Shared/AppGroup/F1E89377-F456-4FC2-BAAC-3DD705EF381A/FiveMinutes.sqlite"

The two apps reads and write to-from two different .sqlite files.

  • On simulator, if I hard-code one of the URLs, both iOS simulator and Watch simulator are able to read-write the same .sqlite file and share the content. However, this is not possible on real devices since the Watch extension cannot write to the iOS path:

URL:file:///private/var/mobile/Containers/Shared/AppGroup/3D05D159-94D6-409C-9A38-90E0830D0C3F/FiveMinutes.sqlite options:(null) ... returned error Error Domain=NSCocoaErrorDomain Code=512 "The file couldn’t be saved." UserInfo={reason=Failed to create file; code = 2} with userInfo dictionary { reason = "Failed to create file; code = 2"; }

1
But did you try to actually put files and access them? God knows how simulator works and what folders does it use. Speaking of watchOS 2.0. Those are native apps now. Shouldn't you also add the entitlement to watch app? - Yaroslav
Yes, I tried to write files and they are put in different locations, iOS cannot access to the watch file and watch cannot access to the iOS file. I added the entitlements to the iOS app, the watch app and the watch extension. The entitlement seems to be added fine, since if I change the entitlement string to something different the returned NSURL becomes nil - LombaX

1 Answers

14
votes

Ok, I think I've found my answer. I remembered that with the transition to Watch OS 2 the extension code is now executed directly on the Apple Watch, and no more on the paired iPhone. So it's seems obvious that the two devices doesn't share the same storage.

The first thing I did was to create a new project, starting from a base iOS Project, and then adding a Watch OS 1 (old version) App Target. In this case, the directories were identical and they could communicate:

Watch Path: file:///Users/Lombardo/Library/Developer/CoreSimulator/Devices/BF52D613-25FF-4092-A5B2-9C3F1B616160/data/Containers/Shared/AppGroup/30B39103-CEEB-4C64-9531-FB27DC40180D/

iOS Path file:///Users/Lombardo/Library/Developer/CoreSimulator/Devices/BF52D613-25FF-4092-A5B2-9C3F1B616160/data/Containers/Shared/AppGroup/30B39103-CEEB-4C64-9531-FB27DC40180D/

Then, I did the first thing every programmer should do: read the docs. In the FIRST PAGE of the WatchOS 2 transition guide there is this sentence:

Your extension now stores files and data on Apple Watch. Any data that is not part of your Watch app or WatchKit extension bundle must be fetched from the network or from the companion iOS app running on the user’s iPhone. You cannot rely on a shared group container to exchange files with your iOS app. Fetching files involves transferring them wirelessly to Apple Watch.