NSUserDefaults not working on Xcode beta with Watch OS2
With watch OS2 you can no longer use shared group containers. Apple Docs:
Watch apps that shared data with their iOS apps using a shared group
container must be redesigned to handle data differently. In watchOS 2,
each process must manage its own copy of any shared data in the local
container directory. For data that is actually shared and updated by
both apps, this requires using the Watch Connectivity framework to
move that data between them.
WatchKit SDK not retrieving data from NSUserDefaults
+standardUserDefaults
returns an NSUserDefaults
object that only saves information for the current process.
If you want to create an NSUserDefaults
object that shares data between your iOS app and one of its extensions, then you'll need to set up an app group container and use that as the basis for sharing information.
From the linked documentation:
After you enable app groups, an app extension and its containing app can both use the NSUserDefaults API to share access to user preferences. To enable this sharing, use the initWithSuiteName: method to instantiate a new NSUserDefaults object, passing in the identifier of the shared group. For example, a Share extension might update the user’s most recently used sharing account, using code like this:
// Create and share access to an NSUserDefaults object.
NSUserDefaults *mySharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.example.domain.MyShareExtension"];
// Use the shared user defaults object to update the user's account.
[mySharedDefaults setObject:theAccountName forKey:@"lastAccountName"];
NOTE: With watch OS2 you can no longer use shared group containers.
Did Apple change NSUserDefaults sharing from iOS app to watchOS app
To answer your first question, both answers you quoted from StackOverflow and Apple are correct. Apple forwards the iOS app's NSUserDefaults
as read-only values, but the watch has it's own NSUserDefaults
for its preferences. The main takeaway from the documentation is for watch apps to move away from shared container groups that use NSUserDefaults
, (as this was how WatchKit
apps were implemented). In watchOS
, Apple has added WatchConnectivity
which is the standard for sharing data between the iOS and watch apps.
To answer your second question, rely on NSUserDefaults
as you would normally to store preferences related to each app separately and use WatchConnectivity
for sharing data between apps.
settings bundle not working on watchOS 2
I've edited my answer. Previously, it spoke about the inability to use App Groups to sync data in watchOS 2, but your specific question is regarding the Settings Bundle, which still syncs from iOS to Apple Watch in watchOS 2.
I am unable to get this to work in Xcode 7.1 / 7.2 in Simulator, but it does work on a real device. From the docs:
Preferences in watchOS 2 are forwarded from iOS to Apple Watch, but any modifications you make are not sent back to iOS. In watchOS 1, WatchKit extensions have direct access to the defaults database and may read and write values.
All 3 targets should have the same App Group configured (the Watch App target here seems to be the missing component in OPs question):
My settings bundle:
Some simple interface code in InterfaceController.swift
:
@IBOutlet var label: WKInterfaceLabel!
@IBAction func buttonAction() {
let sharedDefaults = NSUserDefaults.init(suiteName: "group.testSettings")
let name_preference = String(sharedDefaults?.objectForKey("name_preference"))
self.label.setText(name_preference)
}
and the final outcome:
So, it does work as expected, only not in Simulator. It seems that there is some isolation occurring between the 2 devices in Simulator, and it's a little frustrating trying to put my finger on exactly what's happening there.
iPhone and Apple Watch not sharing App Group
With the introduction of watchOS2
and native watchOS
apps, Apple Watch apps are no longer just extensions of their iOS counterpart and hence they don't share AppGroups.
You cannot use AppGroups for sharing data from watchOS2
onwards. You have to use the WatchConnectivity
framework for sending data between your iOS
and watchOS
apps.
See the Keeping your WatchOS content up-to-date page for more information on the topic.
Get Data from Parent to WatchKit with NSUserDefaults
If you are using watchOS 2.0, shared groups are no longer supported, you must use Watch Connectivity framework instead. See my answer to a similar question here: stackoverflow.com/questions/30851729/… I would recommend switching now as the OS will be out in the fall. – rmp 15 hours ago
Yes this was my Problem thx :)
Watch OS 2 - How store data on Watch for fully native app?
watchOS 2 has access to CoreData, NSCoding and NSUserDefaults. Depends on the data you want to store but those are the best (first party) options.
If you are going to use NSUserDefaults, do not use standardUserDefaults
you should use initWithSuiteName:
and pass in the name of your app group.
You could even make a category/extension on NSUserDefaults to make this easier.
Objective-C
@interface NSUserDefaults (AppGroup)
+ (instancetype)appGroupDefaults;
@end
@implementation NSUserDefaults (AppGroup)
+ (instancetype)appGroupDefaults {
static NSUserDefaults *appGroupDefaults = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
appGroupDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"com.whatever.yourappgroupname"];
});
return appGroupDefaults;
}
@end
Swift
private var _appGroupDefaults = NSUserDefaults(suiteName: "com.whatever.yourappgroupname")!
extension NSUserDefaults {
public func appGroupDefaults() -> NSUserDefaults {
return _appGroupDefaults
}
}
Related Topics
How to Use Special Character in Nsurl
Why Optional Constant Does Not Automatically Have a Default Value of Nil
Nsuserdefaults Not Working on Xcode Beta With Watch Os2
Closure With Generic Parameters
How to Disable Pasting in a Textfield in Swift
Dispatch_Once After the Swift 3 Gcd API Changes
Why Is 'Nil' Not Compatible With 'Unsafepointer≪Cgaffinetransform≫' in Swift 3
How to Check If a Text Field Is Empty or Not in Swift
How to Convert Array of Bytes [Uint8] into Hexa String in Swift
String Value to Unsafepointer≪Uint8≫ Function Parameter Behavior
Why Can't I Instantiate an Empty Array of a Nested Class
Access Firebase Variable Outside Closure
Ios 14 Swiftui Keyboard Lifts View Automatically
Convert a Two Byte Uint8 Array to a Uint16 in Swift