What does "+resetStandardUserDefaults" actually do? - objective-c

Have tried to use "+resetStandardUserDefaults" of the NSUserDefaults class to reset the default values to their "factory" settings. It turns out to be not the appropriate method to use. Find out from some archived discussions in SO that we should use the instance method "removeObjectForKey" to remove the user's settings instead.
But am just curious and hope that someone could explain the actual usage of "+resetStandardUserDefaults". Have read the reference web manual about this. But it is very brief and I don't seem to get what it really means ...

Somewhere (usually in the app delegate +initialize) you declare the standard user defaults (preferences of your app at the first launch).
+resetStandardUserDefaults makes your app mean it's the first launch and uses the user defaults the way you declared them in the app delegate.
THE ABOVE IS THE WRONG ANSWER
As Apple's documentation says, it:
Synchronizes any changes made to the shared user defaults object and releases it from memory
The reset portion refers to the fact that the standardUserDefaults object in memory is destroyed, so you get a fresh one from the file system next time you use [NSUserDefaults standardUserDefaults] but it has nothing to do with any first launch behaviour.
The call would make sense if it was renamed flushDefaultsToDisk or similar. It is the most misleadingly-named part of iOS SDK I've seen so far.
(I corrected this in-place as this rates quite highly on searches and didn't want to put the correction in a comment which someone might not read.)

Related

localStorage not persisting in OSX app (Xcode 4.3)

From what I have seen, if you are building a OSX desktop HTML5 app and want localStorage to persist in your WebView wrapper, you need to do something like this:
WebPreferences* prefs = [webView preferences];
[prefs _setLocalStorageDatabasePath:#"~/Library/Application Support/MyApp"];
[prefs setLocalStorageEnabled:YES];
Taken from: How do I enable Local Storage in my WebKit-based application?
But this doesn't seem to work for me in Xcode 4.3. Instead I get
"No visible #interface for 'WebPreferences' declares the selector '_setLocalStorageDatabasePath:'
"No visible #interface for 'WebPreferences' declares the selector 'setLocalStorageEnabled:'
I'm very new to Objective C, and are probably doing something silly like not including some header or something.
I've included the WebKit framework and both of these headers:
#import <WebKit/WebKit.h>
#import <WebKit/WebPreferences.h>
And what's weird is that I can access other methods of prefs, i.e. [prefs setDefaultFontSize:10] - but just not the two above that I listed.
Any ideas? Is this something that has been removed in Xcode 4.3?
OK, I have a solution. I looked at the source code to macgap and noticed how they were dealing with this issue.
It turns out the error message I was getting does make a little sense - I needed to declare an interface for WebPreferences first.
#interface WebPreferences (WebPreferencesPrivate)
- (void)_setLocalStorageDatabasePath:(NSString *)path;
- (void) setLocalStorageEnabled: (BOOL) localStorageEnabled;
#end
...
WebPreferences* prefs = [WebPreferences standardPreferences];
[prefs _setLocalStorageDatabasePath:"~/Library/Application Support/MyApp"];
[prefs setLocalStorageEnabled:YES];
[webView setPreferences:prefs];
Like I said, I'm new to Objective-C. I don't really get why the interface is needed in order to call those two methods (i.e. when I can call the other methods without the interface).
There's good news and there's bad news; I'm going to make the assumption that you want the bad news first (it'd be easier if I answered your question with the bad news first anyway).
The Bad News
The only answer to why this is happening is that Xcode 4.3 doesn't offer those methods anymore. That question that you linked to, "How do I enable Local Storage in my WebKit-based application?" was last active over a year ago (with the accepted answer being edited in early 2011). There have been at least two updates to Xcode since then (probably more and I'm just not remembering them), and it seems feasible to me that Apple would want to keep their private methods private, so it's safe to assume that they removed them as well as the support for setLocalStorageEnabled:.
The reasons that I don't think that there is any other answer to your problem are the following:
Both methods that you call on the WebPreferences instance are not supported. It's not just the private method, so Apple must have modified the WebPreferences class, removing not only setLocalStorageEnabled: but also support for private methods such as _setLocalStorageDatabasePath:. Why they supported private methods to begin with, I don't know, but they've definitely cracked down on their support because I haven't seen an opportunity to implement a private method in quite some time.
If implementing the private method (or even the other, public method) were possible, it'd be as easy as your code makes it out to be. If one looks at the linked question, they don't mention any difficult steps to getting the code to be supported. There isn't any way to import a private part of a framework such as WebKit without doing some heavy-lifting with regards to not only finding the private part but getting it into your code as well. Even if you can get those methods supported in your code after all of that heavy-lifting, it'd be highly unlikely that Apple would be very happy with it and they'd probably deny your app from the app store.
Sorry to be a Debbie-downer about it all, but I just don't think that your code would work anymore without some deep diggging and large workarounds. If you want it to work easily, you'll probably have to go back to early 2011 and make your app then instead.
The Good News
There is probably some solution that doesn't involve private and unsupported methods that I'm just not aware of because of my lack of experience using WebKit. Instead of looking for an answer for why your code isn't working, I'd start looking for alternatives for what your code is supposed to do.
I have found a solution to the persistence problem. see my post at
Local Storage in webview is not persistent

I'm having trouble applying a solution found in SO in my iOS app. Can someone show me the big picture?

in the Stack Overflow posting:
How do I create a global UIManagedDocument instance per document-on-disk shared by my whole application using blocks?
Alan asked how to create a global UIManagedDocument to be used throughout his entire app. He provided code slices of his attempt. Kevinpo provided an answer which made perfect sense to Alan.
But I started out with the same problem, and can't make heads or tails out of their collective postings.
Specifically:
Alan's code references an object called managedDocumentDictionary,
but does not explain how to create it so I get an 'undeclared
identifier' compilation error.
Alan starts out stating that he wants to create a helper method to
retrieve a UIManagedDocument, yet throughout both his and Kevin's
code, neither actually show defining a helper method with .h and .m
files.
So, if possible, can anyone make sense of what they are saying and help me understand how it all fits together? Perhaps:
A helper Class definition,
How does one get the ball rolling, i.e., where do I initially create this UIManagedDocument,
Once created, How do I get the document in other TableViewControllers?
A sample of where this should be invoked - in the AppDelegate? or each TableViewController?
Maybe even a sample project?
Thanks to all for any interpretations you can offer.
That post shows how to access a document, based on a name. The dictionary is a mapping from names to UIManagedDocument instances. Thus, he can ask for document #"Foo" and the code will go look up #"Foo" in the dictionary. If it is there, the UIManagedDocument will be returned. If it is not there, then a new one will be created and placed in the dictionary (and the passed-in completion block will be called).
His question was basically, how to pass a completion block to the function, and have that function call the completion block he passed in.

UIApplicationWillTerminate: NSNotificationCenter vs Application Delegate

This is just a theoretical question. It was born from a real problem in my app, but I re-designed the problem out of the application. But the question remains:
If in my app delegate I write my singleton object to disk upon applicationWillTerminate: but also use NSNotificationCenter to call updateSingletonData upon UIApplicationWillTerminateNotification in some view controller, which will happen first? Will my data be written to the singleton, then the singleton be written to disk, then the app terminates? Or will the reverse happen, with the singleton being serialized and then the singleton updated (worse), or will the app just terminate after a certain amount of time if the serialization takes too long (much worse!)?
I guess this shows my lack of understanding of the guts of Springboard... thanks to anyone who can shed some light here.
A couple of things to note here:
Only Apple know the order these will happen in, as they wrote the code that does it.
You shouldn't care about the order these will happen in. If you do care, then you've designed your code badly.
In reality, you could go and check what order the happen in - for your particular device, for your particular iOS version, etc.
But really, you shouldn't care what order they happen in. From the sounds of it, you should be either firing off to the view controller to write the data before saving in applicationWillTerminate:, or letting the view controller handle saving after it's written its data.
This question is old and the response by #mattjgalloway is correct in terms of code quality but, for the sake of the knowledge, I just saw in the docs that the notification is posted after the UIApplicationDelegate method is called (emphasis mine):
After calling this method, the app also posts a UIApplication​Will​Terminate notification to give interested objects a chance to respond to the transition.
https://developer.apple.com/reference/uikit/uiapplicationdelegate/1623111-applicationwillterminate

NSUserDefaults, is a good practice to create local value too?

I'd like to know if creating a mirror of values saved in UserDefault is a good practice or not?
For example if I store parameter "A" in UserDefault is it useful to maintain a copy of this value locally and update it when UserDefault changes?
In my app I had the necessity to frequently read parameter "A", and in this case I think it's better to read from an ivar instead of from a NSUserDefault, but I'm not sure about that so I'm asking if there is a good practice to follow.
Seems like extra work and a premature optimization to me.
In all my apps I've always retrieved the NSUserDefaults each time they were needed and it was never an issue. Keeps the code short and obvious. And if it becomes a problem, you fix it, easy as that.
The performance is irrelevant because NSUserDefaults is not intended to hold much information or be used so often as to cause a performance problem.
As for code encapsulation and reuse, don't use NSUserDefaults directly on code that performs specific tasks unrelated to your preferences. eg: a method to colorize an image should take the user preference as a parameter instead. Use it directly anywhere else.

what is the program flow in Cocoa Applcation

I am new to mac os X development ,I downloaded an open source mac application ,but i couldn't able to understand the flow of execution of cocoa program.so any one can explain the program flow of a general cocoa program briefly.
Thanks in advance
Start in main. It's not likely to contain anything interesting, but worth checking just in case. Most probably, it will contain only a call to NSApplicationMain, which will create the NSApplication object and send it a run message. That's what gets the application running, and this method will run for the rest of the rest of the process.
Then look in the MainMenu nib. Loading this is one of the first things the application will do. Any windows here that are set as “Visible on Launch” will come up immediately; more importantly, the application delegate will probably be here. Check the application's or File's Owner's (the application is both of them in this nib, so you need to check both) delegate outlet, and if one of them is connected, follow the connection. See what class that object is an instance of.
Once you've found the application delegate class, open it up in Xcode. Look through the list of application delegate methods and find which ones are implemented, and read the ones that are. The application:…FinishLaunching: twins will be particularly important at the start of the process.
From there, it's all just reading code, seeing what it does, and going where it takes you.
Peter's answers are good - I'd also say to check for implementations of 'awakeFromNib', especially for object loaded from MainMenu.nib. You often find interesting things stashed away in that method, rightly or wrongly.