6
votes

Apple documentation says "Also, iOS automatically forwards a read-only copy of your iOS app’s preferences to Apple Watch. Your WatchKit extension can read those preferences using an NSUserDefaults object...". https://developer.apple.com/library/prerelease/watchos/documentation/General/Conceptual/WatchKitProgrammingGuide/SharingData.html#//apple_ref/doc/uid/TP40014969-CH29-SW1

But I can't read defaults in my WatchKit app that were saved in my iPhone app, am I doing something wrong?

In the WatchKit app, can I even save to (a WatchKit only) defaults, or does that not even work?

iPhone Data:

let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(dataArray, forKey: "DataSaved"

Watch ExtensionDelegate:

let defaults = NSUserDefaults.standardUserDefaults()
print(defaults.arrayForKey("DataSaved"))
print(defaults.objectForKey("DataSaved"))

arrayForKey and objectForKey for print nil.

I must be doing something wrong, do you know what it would be?

4

4 Answers

11
votes

Difference between NSUserDefaults

NSUserDefaults is a unit of memory on any device, so it is completely different in iOS and watchOS, as well in tvOS, etc.

For example, if you run a code that adds a new key called "key1" to NSUserDefaults on iOS (assuming you are using NSUserDefaults.standardUserDefaults()) , when you request to read its data on watchOS, it gives you an empty dictionary.

That's because it the first time, you store the dictionary only in iOS App Target and not in a shared space between two devices. When the WatchKit extension wants to use NSUserDefaults, it reads the (empty) dictionary saved in WatchKit Target and not the (filled) dictionary in iOS Target.

Sharing Data

There are some ways of sharing dictionaries between watchOS and iOS:

1- Using WatchConnectivity framework in watchOS 2, you could pass data between two targets. You can use sendMessage or similar functions in WCSession classes to do so. Just don't forget to add WCSessionDelegate to your InterfaceController (in watchOS) or ViewController (in iOS) classes and app delegates for the app to be able to receive data from WatchConnectivity.

2- Using online/cloud storages, you could upload the dictionary from iOS App there, and then download it to watchOS App. However, this needs an Internet connection, and is not suitable in many cases, for example if your app does not need to connect to the Internet to do other tasks, and you force the user to connect to the Internet just in order to sync a simple dictionary between the two targets.

3- Using App Groups (if you are using watchOS 1), which I don't describe it more, because it is outdated and you probably don't want to make your app just for watchOS 1.

Conclusion

1- NSUserDefaults returns two different dictionaries in watchOS and iOS, respectively.

2- To share data between watchOS and iOS, you could use WatchConnectivity, the Internet (not recommended) and App Groups (in watchOS 1).

More Resources

For more details about WatchConnectivity, the modern answer to your question, you should check out Apple Documentation in Apple Developer Portal.

Also you should see this WWDC session talking about this great framework included in watchOS 2.

3
votes

Sorry. You can't read any defaults in WatchKit app, because from watchOS2 it has it's own memory to be used. so You can not access value from iOS's NSUserDefaults in watchOS

You have to use WatchConnectivity to share data for watch OS2.

2
votes

To be clear, NSUserDefaults.standardUserDefaults() will give you two different dictionaries when calling on the watch and on the phone.

For WatchConnectivity check out https://developer.apple.com/videos/play/wwdc2015/713/

Apple docs:

https://developer.apple.com/library/watchos/documentation/WatchConnectivity/Reference/WatchConnectivity_framework/index.html

0
votes

Ns defaults.standard is particular to that target by using it you can access data within that target, in your case you need to access data in another target so listen you need to do two things one is 1. use app groups 2. don't use user defaults.standard use UserDefaults(suiteName:"group.yourgroup") to store and access the data refer this Link might be useful.