Can't sync NSUserDefaults with apple Watch - ios

I need to pass 2 doubles to apple watch, for this purposes I set app groups in extension and main app, next:
main app:
groupDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.XXXXX"];
[groupDefaults setDouble:pitchDelta forKey:#"pitch_delta"];
[groupDefaults setDouble:rollDelta forKey:#"roll_delta"];
[groupDefaults synchronize];
extension:
groupDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.XXXXX"];
double pitchDelta = [groupDefaults doubleForKey:#"pitch_delta"];
double rollDelta = [groupDefaults doubleForKey:#"roll_delta"];
But the values are not passed. Did I forget something?
in main app code
[groupDefaults setDouble:pitchDelta forKey:#"pitch_delta"];
[groupDefaults setDouble:rollDelta forKey:#"roll_delta"];
[groupDefaults synchronize];
NSLog(#"%f %f", [groupDefaults doubleForKey:#"pitch_delta"], [groupDefaults doubleForKey:#"roll_delta"]);
returns in log -0.387812 -0.098052

Try deleting the apps entirely from device & watch and try again.
I had the same problem testing this with the Today extension.
Also check on the developer portal, that your App Id correctly has the app groups permission enabled, despite what you might see on Xcode

If you use simulator,you can find whether those data were successfully persisted.
In my case the path is:
/Users/benson/Library/Developer/CoreSimulator/Devices/C4557E97-F6E4-48A9-B1C7-04441B3A0214/data/Containers/Shared/AppGroup/991C1FE1-6839-441E-A2F4-66834A683153/Library/Preferences/group.XXXXX.plist
Open group.XXXXX.plist file,find if those values exist or not.

In the simulator, synchronizing NSUserDefaults does currently not always work. This is a well-known issue. I've spent quite some time searching for mistakes in my code and at the end it turned out that my code works perfectly on the actual Apple Watch.
However, I'm not sure if it is possible to write with such a high frequency. How do you ensure synchronization?

You need to implement shared container for having communication between main app and extension.
Check out the given link for watch kit tutorial :-
https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/WatchKitProgrammingGuide/DesigningaWatchKitApp.html#//apple_ref/doc/uid/TP40014969-CH3-SW4

Related

NSUserDefaults Not Saving Data. Limits?

I have such a problem: the syntax of saving data in userDefaults is clear and was working everyday in app. Today i have such a problem that nothing is stored after synchronize. P.S i have no syntax error.
here is an example of saving and reading:
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"StackOverflow"];
[[NSUserDefaults standardUserDefaults] synchronize];
And reading
BOOL stackOverflow = [[NSUserDefaults standardUserDefaults] boolForKey:#"StackOverflow"];
I know information about mutableCopy but in this simple situation it's not needed.
So is there any limits for userDefaults? I am testing on real device and storage i have up to 50GB free. I know that userDefaults are stored in plist file which in critical situation could be 1MB but i even dont exceed 1kb :( ...
using latest xcode and latest iOS version on 6S.
Need Advice. Thanks For help.
So after half hour morning work i find the solution and actually the problem. Case such as mine in 90% it is developers fault, so it was.
I had more than 30 user defaults value's, in which for e.g 15 of them had initWithSuitName (Identifier), everything saved with identifier id was working well but saving value without it was broken because of preferance conflicts.
Solution: I replaced unnamed userDefaults with identifier and everything has fixed.
In Case of some problem with NSUserDefaults:
NSUserDefaults - is thread safe.
Synchronize - Saves data immediately
Saving Data - If app will terminate chance of losing data is 50%, after debug Stop button tapped is same scenario. P.S data lose will be 50% if it's not saved in right place.
Debuging NSUserDefaults - in debugger you can simply tipe po [[NSUserDefaults standardUserDefaults] dictionaryRepresentation] and po [[NSUserDefaults standardUserDefaults] valueForKey:#"KeyForSavedData"]
Shared Container Example - if you want to share property for example between app and extension you can simply type appGroup identifier inside initWithSuitName:#"com.Example.ExampleAPP"
I faced this issue before. I just remove the key before add it to new object.
Example
[NSUSER removeObjectForKey:#"savedData"];
[NSUSER setBool:YES forKey:#"savedData"];
[NSUSER synchronize];
Note:
If you are used so many no of NSUSER then it act like ridicules. This is by my little experience.

NSUserDefault with App Group is not working in iOS 8 Beta3

I have to save Boolean Value to NSUserDefault in my App with custom keyboard extension and share with App Group.
My Code is worked in iOS 8 Beta1.
self.defaults = [NSUserDefaults standardUserDefaults];
if([self.defaults boolForKey:#"BlackKey"])
{
NSLog(#"Black");
}
else
{
NSLog(#"White");
}
But Not in iOS 8 Beta3. When i retrieve Boolean value from NSUserDefault , it's return nothing and i can't load from custom keyboard extension.
I have also tried with initWithSuiteName in NSUserDefault. Am i only one for that problem or bugs of iOS 8 Beta3?
A few probable solutions are:
Your app group is not setup correctly, or you are not using the correct group identifier with initWithSuiteName:
You have not enabled network access for your keyboard. This document states the following when you have network access disabled for your keyboard (default behavior):
No shared container with containing app
It's a bug.
Try using
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"BlackKey"];
when you save and read it by using this code:
if([[NSUserDefaults standardUserDefaults] boolForKey:#"BlackKey"]) {
NSLog(#"Black");
}
else
{
NSLog(#"White");
}
or if you already done so, then it can be bug, and Xcode 6 beta versions also have other bugs so it's safer to try in Xcode 5 or older.

is that possible to know my apps is first time run or not in xcode?

i create an apps that i want to prompt an message for the user.. maybe using UIAlertview. After that, if the user run the apps for the second time, the alert won't prompt up anymore.
is that possible? honestly i don't have any idea about how to doing this.
Any idea? I search on STO, actually this link, still confused.
what is NSUserDefaults? How can NSUserDefaults store this information? i mean this is my first time or second time.
thanks.
To know what's NSUserDefaults, I suggest to take a look the official doc.
And of course you can use it to fulfill your goal.
You use a user default to store information about the current amount of runs in the app.
More or less like:
BOOL isRunMoreThanOnce = [[NSUserDefaults standardUserDefaults] boolForKey:#"isRunMoreThanOnce"];
if(!isRunMoreThanOnce){
// Show the alert view
// Then set the first run flag
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"isRunMoreThanOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Yes, U can save a value in NSUserDefault for the first time in your app & set it some other value once you open the app.
like
if(![[NSUserDefault standardUserDefault] objectforKey:#"AppOpenFirstTime"])
{
// App Open First time
// Show Alert
[[NSUserDefault standardUserDefault] setObject:#"1" forKey:#"AppOpenFirstTime"]
}
You can check if you stored some value in NSUserDefaults
NSString *flag = [[NSUserDefaults standardUserDefaults] stringForKey:#"not_first_run"];
if (!flag) {
//first run, do somethig
}
and then set it to some value
[[NSUserDefaults standardUserDefaults] setObject:#"just any string" forKey:#"not_first_run"];
NSUserDefaults is a key-value store saved between your application launches.
You can do it exactly as cortez said in your link. NSUserDefaults is written to disc, and will be created and accessed from your app.
See this link
First Time when your application launch at that time boolForKey:#"AlreadyRan" is FALSE. after that set it TRUE.
if(![[NSUserDefaults standardUserDefaults] boolForKey:#"AlreadyRan"] )
{
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"AlreadyRan"];
}
With the NSUserDefaults class, you can save settings and properties
related to application or user data.
The objects will be saved in what is known as the iOS “defaults system”.
The iOS defaults system is available throughout all of the code in your app, and any data saved to the defaults system will persist through application sessions.This means that even if the user closes your application or reboots their phone, the saved data will still be available the next time they open the app!

How to determine that user runs the app for the first time?

I got a problem of my iOS app recently. In my app, an instruction view will appear at the first time of running, then hide from then on. How can I implement this effect?
Try to use this function:
- (BOOL) isFirstRun
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"isFirstRun"])
{
return NO;
}
[defaults setObject:[NSDate date] forKey:#"isFirstRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
return YES;
}
In your app delegate check for a key in the user defaults (your own custom key, something like "AppWasAlreadyStartedPreviously"). If the key doesn't exist yet, it's the first run. You can show your instruction view and add the key to the user defaults. The next time the user starts the app you'll find the key in the user defaults and know that it's not the first run.
See the documentation of NSUserDefaults.
Store a file and check if the file exsists every time when you start the app. If tr file does not exsists then show intro, and then create the file.
The only way I think is to store a value into a specified file, when run the app, you should check the value first, and then you can deal with the result whether the app has already been run.

Cant able to get phone number from iphone

Currently I'm using the following code to get the local device phone number :
NSString *num = [[NSUserDefaults standardUserDefaults]
stringForKey:#”SBFormattedPhoneNumber”];
NSLog(#”Phone Number: %#”, num);
but it can't able to get the number, it shows null. Can any one guide me how to solve this problem!!
Thanks in advance
There is no supported way to get the device's phone number. Any method (such as "SBFormattedPhoneNumber" mentioned in the other answers) that happens to work for now is liable to get your app rejected and is liable to stop working at any point without notice.
If you need the phone number, just ask the user to enter it.
Use below code
To Store a phone number string
[[NSUserDefaults standardUserDefaults] setObject:#"1234567890")
forKey:#"SBFormattedPhoneNumber"];
To get the phone string back.
NSString* num = [[NSUserDefaults standardUserDefaults] objectForKey:#"SBFormattedPhoneNumber"];
Read the blog tutorial.
http://ayeapi.blogspot.com/2009/12/sbformatphonenumber-is-lie.html
Here is the solution !!! Check this link or read answer below from same link !!!
Answer from LINK:
Just to expand on an earlier answer, something like this does it for me:
NSString *num = [[NSUserDefaults standardUserDefaults] stringForKey:#"SBFormattedPhoneNumber"];
Note: This retrieves the "Phone number" that was entered during the iPhone's iTunes activation and can be null or an incorrect value. It's NOT read from the SIM card.
At least that does in 2.1. There are a couple of other interesting keys in NSUserDefaults that may also not last. (This is in my app which uses a UIWebView)
WebKitJavaScriptCanOpenWindowsAutomatically
NSInterfaceStyle
TVOutStatus
WebKitDeveloperExtrasEnabledPreferenceKey
and so on.
Not sure what, if anything, the others do.
Saving Data to NSUserDefaults.
[[NSUserDefaults standardUserDefaults] setObject:#"1234567890")
forKey:#"SBFormattedPhoneNumber"];
NSString* num = [[NSUserDefaults standardUserDefaults] objectForKey:#"SBFormattedPhoneNumber"];
It may help you..

Resources