Modifications on objects in NSUserDefaults-bound NSArrayController not saving - nsuserdefaults

In my project, I have an NSArrayController bound to save to a the application's standard defaults (NSUserDefaults). This in itself works perfectly - objects added are saved and restored as expected.
However, if I programmatically modify one of the NSMutableDictionaries contained in the NSArrayController's array, none of the changes are saved. Only values set with the creation of the dictionary seem to stick.
I suspect this is because simply calling setObject:forValue: on the dictionaries in the array doesn't notify the controller of changes, but I'm not sure. Am I doing something wrong?
UPDATE: I have since switched from NSMutableDictionary to a custom object that conforms to KVC (to the best of my knowledge - I'm using properties so that should be taken care of) as well as NSCoding. It can and does save and restore fine - it's just not consistent. It kinda saves whenever it feels like it instead of when I update a property.

Well, I ended up just writing my own controller responsible for loading and saving downloads to their own plist file. It saves when it's told to without fail, so the problem is solved.

Related

Does calling removeFromSuperview() on lazy created view instantiate it?

In one of my view controllers, I have a lot of possible subviews that can be created based on the status of the data received. I am trying to make them class variables so they can be accessible throughout the file and am using lazy so that I don't create views I don't need. However, I need to make sure the views that could be displayed get removed if the status changes and would want to call .removeFromSuperview(). But I know that lazy variables get initialized the first time they get referenced and that would defeat the purpose of trying to save memory.
Yes, if you referenced the lazy variable in order to call removeFromSuperview, it would first create the view and then call removeFromSuperview on it. You should likely design another way, without lazy. I would recommend starting with the simplest approach (such as Optional properties, checking if it's nil, and creating it if necessary), and then extracting duplicated code. lazy solves one very specific problem in a very limited way. If you don't need precisely what it offers, you generally will need to build something custom

ViewWillAppear or NumberOfCellsInSection? which will happen first?

I'm working on this app that uses parse.com, and I have to make a Query and make the objects into arrays. I made that into a method and put it in viewWillAppear method, but I still see nothing!
I don't know where else to put it, nor how can I make it call the method getObjects() whenever the viewWillAppear is called, and then apply it to the tableview.
You can always check that out by putting a println("we are in xxx") in those methods to checkout which one loads the first.
But do you reload your tableView data :
self.tableView.reloadData()
after you loaded your parse data ?
This is a very common scenario and will be a breeze to accomplish with the right tools. You can build out your own functionality for Parse within a TableViewController or you can use Parse's own PFQueryTableViewController to accomplish exactly what you want very easily.
Check out a tutorial to help get you started
Here's another just in case
The gist of it is, you must query Parse for data to fill the TableViewController's data source and then reload the table's data once it is fetched. With PFQueryTableViewController, all you have to do is specify a query in the function queryForTable(). PFQueryTableViewController is included in the ParseUI framework (along with a bunch of other great tools) which you will want to import.

Unknown class in Interface Builder file

Why am I still getting this error when I run my iPhone app? The file is a ViewController that I have been working to delete and replace, but it just won't die. As far as I know, I don't have any reference (string or otherwise) to this file in my project.
I have deleted the related file (I'm trying to get rid of it.)
I have cleaned the project and rebuilt.
I have "Reset Content and Settings" in my simulator.
I have done a grep (grep -i -r "TheClassName" *) and nothing matches except my UserInterfaceState.xcuserstate file.
I have searched the code using XCode's Find/Replace tab.
I have double checked my Build Phases and am pretty sure it isn't in there (its a large project).
Any other ideas? I've spent way too many hours trying to figure this simple thing out; I must be missing something.
Thanks!
Check your nibs or storyboard, and make sure none of your views are set to the class!
I finally fixed the problem after trying it on multiple machines over the course of almost 2 days! I will not be thwarted!
I tracked the problem down to a call to setViewControllers on a UINavigationController which is called on initialization of the application. I was always being passed 3 objects (there are 3 panes in the navigation controller). Even though I had deleted the third object, as previously explained, three objects would always be passed in. The class type of the first two was correct, but the third would just be a UIViewController. Curiously, this view controller had a nibName which corresponded to the object file and Xib file that I had previously deleted. Of course, when view was called on this borked UIViewController, it would crash since the corresponding nib had obviously been deleted. Remember, the textual name of this object or Xib could not be found in my directory with grep, so I have absolutely no idea how in the world it came into existence when I ran my app.
So, I figured the app may not have been cleaned properly. I double and triple checked this. I even validated that my Workspace settings were correct (File->Project Settings->Advanced). The app was indeed being recompiled fresh every time.
Secondly, I started thinking that perhaps the object was being set by some other means. Working backwards, I added some breakpoints and found out that initWithCoder was being called on the parent UINavigationController--this was eventually working down to call the setViewControllers on the object and assigning the three view controllers (one of which was the offending one). I could easily see from the call stack that the Nib file that was being loaded was deserializing something offensive.
So, I started digging into my Xib file. Of course, the object name wasn't in the file (as expected since the grep didn't find anything). I deleted and recreated the portion of the Xib that included my root UINavigationController. This ended up changing the Object ID and ref within the Xib file.
Secondly, I created a new Xib and UIViewController with the same names as the one which I had previously deleted, hoping that Xcode might be happy if I created and then re-deleted them. I then compiled, re-deleted them, updated by Xib file yet again, reverified with grep that yes, indeed, nothing existed with that name.
And it worked. After spending multiple days on this issues, I'm fairly sure that there is a bug here in the interface builder, but do I want to revisit this problem to file a bug report? Absolutely not...
In my case, I solved an issue by name of Custom class name of View instead of Custom class of ViewController. By mistake i added like this for view as shown below.
It Should be for ViewController like this.
This is in my case, for you may be it's related with another component.
This happens when the view class is in a framework. Select the framework's module. Example with a CocoaPod: HSegmentControl.
Make sure when you add or rename or move files around especially in folders, that when you add them you:
A. Create Groups, not references they don't usually read in.
B. Check the boxes for the apporpriate "Product(s) or Target(s)" you want to add the source to.
Another thing to try :
I had to toggle "Inherit from Target" under the "Module" control of "Custom Class."

How should I add items to a list in Core Data now that xcode 4 changed the generated code?

I have a core data model with a parent item and child items under it. In Xcode 3, when I generated the NSManagedObjects for this, I had methods called addChildsObject object method on Parent, but this has gone away in Xcode 4 (see Xcode4: Different code generated for custom core data managed objects). My question is this: how should I be adding the children to the parent now? I really don't want to mess with the generated code, revert to using Xcode3, or add a category to Parent to bring back the missing methods. Is there an approved way, or did Apple just muck up the whole process?
After discovering and reviewing the documentation on Dynamically-Generated Accessor Methods, it appears that Apple still recommends using the now non-existent methods, so it would appear that they have just screwed up by removing them. There is, however, another recommended way of doing this:
NSMutableSet *children = [parent mutableSetValueForKey:#"child"];
[children addObject: child1];
[children removeObject: child2];
This is not fabulous, because it relies on an unchecked string name, but it's the only remaining recommended way to do this without custom implementations. Thanks a lot Apple!

Where's the best place to put your NSUserDefault save/load code?

Using NSUserDefaults to save/load a few small values... it's pretty straightforward.
But WHERE would I place my SAVE or LOAD code?
I want the defaults to LOAD only if/when a certain view is displayed.
I want the defaults to SAVE, only when that view is exited/unloaded/hidden.
(I created a simple app using the "view-based template" and have my string values on the view, inside of UITextFields.)
How about the viewWillAppear and dealloc/viewDidDisappear methods of that view's UIViewController?
Well, your talking about views so:
viewDidLoad / viewWillLoad
viewDidUnload / dealloc
Seem like good candidates. Also, in your init methods, especially if you want to initialize iVars at that point to something from NSUserDefaults.
You should always put the code itself into its own file pair to manage the user defaults, and this module should be responsible for serialization and deserialization, though objects that are serialized should own that virtuosity themselves. You get only the settings you absolutely need in viewDid Load, so as not to slow down the initialization.
If you have capacious user settings, arrays and dictionaries, multiple session data, don't make the mistake of storing them under a single dictionary and key. Split them up.
If your app requires users log on (I do crypto so most of mine do) then only after logon, verifying password from a minimal load of user settings, should you go on to load the heavier session settings. This is on "user time" anyway.