23 Replies
      Latest reply on Sep 29, 2015 10:07 AM by just.do.it
      Universalis Level 1 Level 1 (10 points)

        In the original WatchKit, one could set up a WatchKit settings bundle which would specify settings to be included in the app's page within the Apple Watch app.

         

        The settings were written to a shared NSUserDefaults identified by an app group name.


        The WatchKit extension would be given an App Groups entitlement to allow it to read the shared NSUserDefaults.

         

        All this worked well in the original WatchKit. I know, because I used it.

         

        With Watch OS 2, the WatchKit extension runs on the watch and not on the phone. App Groups are [apparently] no longer used. At least, I have tried using them and the settings do not transfer from the iPhone to the watch.

         

        So: in Watch OS 2, how and where are the settings specified by the WatchKit settings bundle stored, and how can they be retrieved by the extension running on the watch?

        • Re: WatchKit settings bundle in 2.0?
          just.do.it Level 3 Level 3 (445 points)

          Hi,

           

          I've asked the same question some time ago: Can't get settings bundle to work

          No answer so far.

           

          Dirk

          • Re: WatchKit settings bundle in 2.0?
            StephenJohnson Level 1 Level 1 (0 points)

            I am having the same issue, has anyone figured this out?

              • Re: WatchKit settings bundle in 2.0?
                fabiankr Level 1 Level 1 (10 points)

                NSUserDefaults (even with an App Groups) don't sync between the iPhone and the Watch. If you want to sync settings from either your iPhone app or the Settings-Watch.bundle, you have to handle the syncing yourself.

                 

                I've found that using WatchConnectivity's user info transfers works really well in this case.

                Below you'll find an example of how you could implement this. The code only handles one-way syncing from the phone to the Watch, but the other way works the same.

                 

                In the iPhone app:

                1) Prepare dictionary of settings that need to be synced

                - (NSDictionary *)exportedSettingsForWatchApp
                {
                    NSUserDefaults *userDefaults = [self userDefaults]; // the user defaults to sync
                
                    NSSet *keys = [self userDefaultKeysForWatchApp]; // set of keys that need to be synced
                    NSMutableDictionary *exportedSettings = [[NSMutableDictionary alloc] initWithCapacity:keys.count];
                
                    for (NSString *key in keys) {
                        id object = [userDefaults objectForKey:key];
                
                        if (object != nil) {
                            [exportedSettings setObject:object forKey:key];
                        }
                    }
                
                    return [exportedSettings copy];
                }
                

                 

                2) Determine when the settings need to be pushed to the Watch

                (not shown here)

                 

                3) Push the settings to the Watch

                - (void)pushSettingsToWatchApp
                {
                    // Cancel current transfer
                    [self.outstandingSettingsTransfer cancel];
                    self.outstandingSettingsTransfer = nil;
                
                    // Cancel outstanding transfers that might have been started before the app was launched
                    for (WCSessionUserInfoTransfer *userInfoTransfer in self.session.outstandingUserInfoTransfers) {
                        BOOL isSettingsTransfer = ([userInfoTransfer.userInfo objectForKey:@"settings"] != nil);
                        if (isSettingsTransfer) {
                            [userInfoTransfer cancel];
                        }
                    }
                
                    // Mark the Watch as requiring an update
                    self.watchAppHasSettings = NO;
                
                    // Only start a transfer when the watch app is installed
                    if (self.session.isWatchAppInstalled) {
                        NSDictionary *exportedSettings = [self exportedSettingsForWatchApp];
                        if (exportedSettings == nil) {
                            exportedSettings = @{ };
                        }
                
                        NSDictionary *userInfo = @{ @"settings": exportedSettings };
                        self.outstandingSettingsTransfer = [self.session transferUserInfo:userInfo];
                     }
                }
                

                 

                In the Watch extension:

                4) Receive the user info transfer

                - (void)session:(WCSession *)session didReceiveUserInfo:(NSDictionary<NSString *, id> *)userInfo
                {
                    NSDictionary *settings = [userInfo objectForKey:@"settings"];
                    if (settings != nil) {
                        // Import the settings
                        [self importSettingsFromCompanionApp:settings];
                     }
                }
                

                 

                5) Save the received settings to the user defaults on the Watch

                - (void)importSettingsFromCompanionApp:(NSDictionary *)settings
                {
                    NSUserDefaults *userDefaults = [self userDefaults]; // the user defaults to sync
                
                    NSSet *keys = [self userDefaultKeysForWatchApp]; // set of keys that need to be synced
                    for (NSString *key in keys) {
                        id object = [settings objectForKey:key];
                        if (object != nil) {
                            [userDefaults setObject:object forKey:key];
                        } else {
                            [userDefaults removeObjectForKey:key];
                        }
                    }
                
                    [userDefaults synchronize];
                }
                
              • Re: WatchKit settings bundle in 2.0?
                PrinceCreed Level 3 Level 3 (290 points)

                In watchOS 2 you can only read Settings-Watch.bundle.

                To access app settings you should only initialize a suite name for your specific app group, just as you done in watchOS 1.

                • Re: WatchKit settings bundle in 2.0?
                  spybart Level 1 Level 1 (0 points)

                  People are saying this works but I still cannot get it to work even though it was working in watchOS 1.

                   

                  1. I added the shared group to both iOS app and watch extension with the same bundle identifier

                  2. I added the Settings-Watch.bundle to the iOS app and added the ApplicationGroupContainerIdentifier to the Plist

                   

                  I can see the options I added in the Watch app (on iPhone) but the watch doesn't read the settings. What am I missing? I don't have to do anything related to WatchConnectivity to get this thing working right? Are the people that are claiming that it works sure you are on WatchOS 2?

                    • Re: WatchKit settings bundle in 2.0?
                      Coolioxlr Level 1 Level 1 (10 points)

                      I doubt people still work on watchOS 1 app.  Mine work on the device with watchOS2 and no WatchConnectivity involved. FYI it dosen't work on beta5 but GM built works for me.

                        • Re: WatchKit settings bundle in 2.0?
                          PrinceCreed Level 3 Level 3 (290 points)

                          Yes, in watchOS GM built it "just works".

                            • Re: WatchKit settings bundle in 2.0?
                              spybart Level 1 Level 1 (0 points)

                              I'm trying this on GM and it is not working.

                               

                              Ugh. I guess I have no choice but to try to get this working on an empty project then check each setting to see which random setting will magically make it work.

                                • Re: WatchKit settings bundle in 2.0?
                                  spybart Level 1 Level 1 (0 points)

                                  I'm ready to give up and become a farmer for the rest of my life. There is no reason why this shouldn't be working.

                                   

                                  Can this give a hint or spark some light bulb for anyone? The code below produces different output on the iOS app and the watch extension.

                                   

                                  NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.emergingmarkets.commoditiesLite"];
                                  NSLog(defaults.dictionaryRepresentation.description);
                                  
                                  

                                   

                                  On iOS app the output is:

                                  {
                                      AddingEmojiKeybordHandled = 1;
                                      AppleITunesStoreItemKinds =     (
                                          audiobook,
                                          "tv-episode",
                                          booklet,
                                          software,
                                          "software-update",
                                          "itunes-u",
                                          ringtone,
                                          "tv-season",
                                          movie,
                                          mix,
                                          newsstand,
                                          song,
                                          wemix,
                                          tone,
                                          artist,
                                          "podcast-episode",
                                          podcast,
                                          document,
                                          eBook,
                                          album,
                                          "music-video"
                                      );
                                      AppleKeyboards =     (
                                          "en_US@hw=US;sw=QWERTY",
                                          "emoji@sw=Emoji",
                                          "en_US@hw=US;sw=QWERTY"
                                      );
                                      AppleKeyboardsExpanded = 1;
                                      AppleLanguages =     (
                                          "en-US"
                                      );
                                      AppleLanguagesDidMigrate = "9.0";
                                      AppleLocale = "en_US";
                                      ApplePasscodeKeyboards =     (
                                          "en_US@hw=US;sw=QWERTY",
                                          "emoji@sw=Emoji",
                                          "en_US@hw=US;sw=QWERTY"
                                      );
                                      "GC*0" = 0;
                                      "HG*0" = 0;
                                      MSVLoggingMasterSwitchEnabledKey = 0;
                                      NSInterfaceStyle = macintosh;
                                      NSLanguages =     (
                                          "en-US",
                                          en
                                      );
                                      PKEnableStockholmSettings = 1;
                                  }
                                  
                                  

                                   

                                  On watch extension the output is:

                                  {
                                      AppleKeyboards =     (
                                          "en_US",
                                          emoji,
                                          "en_US"
                                      );
                                      AppleKeyboardsExpanded = 1;
                                      AppleLanguages =     (
                                          en
                                      );
                                      AppleLanguagesDidMigrate = "2.0";
                                      AppleLocale = "en_US";
                                      MSVLoggingMasterSwitchEnabledKey = 0;
                                      NSInterfaceStyle = macintosh;
                                      NSLanguages =     (
                                          en
                                      );
                                  }
                                  
                                  
                                  

                                   

                                  The values for the keys "GC*0" and "HG*0" (seen in the iOS app output) are the only ones that come from the Settings bundle. They are the ones that are suppose to show up in the watch extension also.

                                   

                                  Helppppppppppppppp

                                • Re: WatchKit settings bundle in 2.0?
                                  spybart Level 1 Level 1 (0 points)

                                  Do you have a WCSession object? Are you doing anything about WatchConnectivity? Are you doing anything at all different in WatchOS 2?