Storing/Loading NSArray to NSMutableDictionary - objective-c

I have a NSMutableDictionary of NSArrays stored in the AppDelegate. I need to add new NSArrays in one view controller and load the contents of the NSMutableDictionary in another view controller. I am using a shared appDelegate but for some reason the xcode hangs. Also I don't see any error in the debugger. THis is getting frustrating.

Related

How to pass a NSMutableArray including NSManagedObjects to another view controller?

I embedded 'Core Data' into my app. I use a predicate and fetch the result. I use a mutableArray called "fetchedObjects" to get the (predicated and then fetched) result. Now I need to pass this result to another view controller. How can I do that?
1.First thing I tried is using 'NSCoding' but it didn't work out. I think Core Data doesn't comply with NSCoding, am I right?
If I can use 'NSCoding', how do I do it? I tried to save and then load the fetchedObjects but it didn't work out.
2.Off course I can define a pointer using
"product = [[Product alloc] initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];"
but how can I get just the "fetchedObjects" mutableArray but not all the objects?
3.Do you know a better way to pass a NSMutableArray having NSManagedObjects in it? and how can we pass the NSManagedObjects to the other view controllers, only in the context?
Thanks!
You could use an NSNotification.
Say View Controller A fetches the results, and View Controller B needs them.
in VCA:
NSArray *data = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
[[NSNotificationCenter defaultCenter]
postNotificationName:#"newFetchedDataNotification"
object:nil
userInfo:#{#"data": data}];
in VCB:
in viewWillAppear, start listening for the notification:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(processData)
name:#"newFetchedDataNotification"
object:nil];
and add a method:
- (void)processData:(NSNotification *)notification
{
NSArray *data = [notification.userInfo objectForKey:#"succeeded"]
}
And don't forget to unregister for notifications in viewWillDisappear:
[[NSNotificationCenter defaultCenter] removeObserver:self];
I still think the preferred way is using an NSFetchedResultsController to do a first fetch and be notified when objects change. Take a look at this tutorial:
http://www.raywenderlich.com/999/core-data-tutorial-for-ios-how-to-use-nsfetchedresultscontroller
PS: NSManagedObjects are just like any other objects, no need to use encoding. You need to be careful when modifying and saving them though!
Rather than passing the managed objects directly, if all them are already saved I would pass the ObjectID or the unique url, and have the receiver retrieve them from the store.
Retrieving is fast, and also will avoid many problem that may occur with concurrency.
If the receiving controller just need to display data, I would also think about retrieving just the properties you need with an NSDictionary result type, and pass the resulting array to the controller. But of course, I don't know anything about your design.
UPDATE
If I understood correctly your comment, the big advantage of NSFRC is the bunch of delegate methods it brings with it. If you made your UIViewController the delegate of your NSFRC which is NSFetchedResultsControlerDelegate then the fetched controller itself will invoke your view controllers implemented delegate methods, as soon as there's a change in the model. Then within this methods you have to refresh your table view.
The view is not going to be refreshed by itself.
The difference is that if your UITableView datasource is just an array of managed objects, you would need to build by yourself all the logic to react to model change, recognize which cell need to be refreshed, then decide if it deleted/updated/moved etc.. if you think about it, it is quite a few logic to be implemented, and will not be as efficient as the NSFRC is which is already customized for this purpose.
Also, by reading the rest of your comment, you cannot pass a NSFetchedResultsController, well I suppose you can, but it is useless, the NSFRC is meant to be created and used in the UIViewController on screen. The NSFRC is instantiated with few parameters, one of them is a NSFetchRequest, so you have to customize your request to retrieve the objects you need.
P.S.
Sorry, at the moment I am behind a company firewall which is blocking many sites (including Apple docs), therefore I cannot give you any links.
In simple way ,
VC2.h
#property (strong) NSMutableArray *device;
VC2.m
#synthesize device;
Now in Your VC1 from which you want to pass array
VC2 *v2=[VC2 alloc]initWithNibName:#"VC2" bundle:nil];
v2.device = array;
[self.navigationController pushViewController:v2 animated:YES];
or if you are not using Navigationcontroller.
[self presentViewController:v2 animated:YES completion:nil];

Can't add object to NSMutableDictionary (iOS, Objective-C)

I am trying to add an object to an NSMutableDictionary using the setObject:forKey: function,
but for whatever reason, when I run my app in the iPhone simulator and try to perform the action, the code stops at the line were I am trying to add the object to the dictionary. The line where the program gets stuck is as follows:
[_dict setObject:_tf.text forKey:[NSString stringWithFormat:#"keywords_%i", [_keywordsArray count]]];
Where '_dict' is an NSMutableDictionary object, '_tf' is a UITextField, and '_keywordsArray' is an NSMutableArray.
Overall, I am using the objects (aka keys) from my dictionary to populate an NSMutableArray, which is used to fill a UIPickerView. Initially, I load the dictionary from a .plist file, and I can tell the NSMutableDictionary and the NSMutableArray are both getting populated/filled correctly, and that the UIPickerView is working fine, the only part that isn't working is adding objects to the NSMutableDictionary (when the user presses a button in the UI). Also, I did get an error once that said that the NSMutableArray had a count of 0 (zero), when clearly it didn't.
Any help/suggestions would be greatly appreciated!

NSCollectionView's setContent: memory management

I have a NSCollectionView that I populate using [collectionView setContent:data]; where data is a NSArray filled with objects all of the same custom NSObject subclass. The item prototype of the collection view is a standard NSCollectionViewItem, not subclassed. The collection item's view is populated using bindings from my NSObject subclass.
Now to the problem, when analyzing my app using heapshots I see that there is a huge increase in memory when opening the window with the collection view. Instruments pinpoints this memory increase to the [collectionView setContent:data]; line. This memory is never reclaimed. Any ideas?
EDIT: I access the data object like this:
NSArray *data = [[[[MWWeatherController sharedInstance] cachedData] objectForKey:[NSString stringWithFormat:#"%u",index]] objectForKey:#"daily"];
Have you made the ViewController for the CollectionView KVO compliant?
Has the XIB for the CollectionView an ArrayController?
Bind the CollectionView of the XIB to the arrangedObjects of the ArrayController and set the Items through your ViewController method e.g. setMyCustomObjectsArray, that again sets the array that is observed by the ArrayController.
Make sure you release everything correctly in your custom object's dealloc method too.
I think you are not releasing data in your scope ... if you own the 'data' object make sure you release it.
Some query to answer it better --
How you allocate 'data'?
Who is releasing it?
[collectionView setContent:data]; more code snippet around this line

why using NSArray (and other non-display graphic element) into Interface Builder

using IB, i found that you could use NSArray not in a programatic way. I was thinking, great, i can make sets of uiviews into an NSArray and then get a proper outlet in xcode and retreiving all my uiviews from the NSArray.
The fact is when i put a NSArray into the nib file, i can't do nothing into it's property list. So the fact is i don't use the NSArray the correct way it should be. So is there anyone who could explain me how can i use my nsArray the way i want to? This will explain me why using non-display class into the nib file, and the purpose of it.
Thanks.
You can instantiate an NSArray instance in a nib file using the "Object" item in the IB library...but you probably don't want to.

Am I updating my NSArray that's bound to an NSTableView right?

I have a pretty standard setup where I have an array in my controller that I'm binding to an NSTableView. When I add an object to this array with the UI, I add elements by copying the array to a mutable array, adding the contents, then copying it back. I saw this idiom somewhere, but I'm not really sure where, or whether this is actually a sane thing to do. I t works fine on Snow Leopard, but it crashes really badly on Leopard. GDB tells me it happens right at the marked line, where I copy the new array back.
#interface MyAppDelegate : NSObject {
NSArray * urls;
//other declarations
}
#property (nonatomic, retain) NSArray *urls;
#implementation MyAppDelegate
#synthesize urls;
- (void)addThing:(id)sender {
NSMutableArray *newUrls = [NSMutableArray arrayWithArray: [self urls]];
[newUrls addObject: newurlimadding];
[self setUrls: [NSArray arrayWithArray: newUrl]];
}
I'm pretty sure I must be doing something boneheaded here. Is there a better way to do this? Why am I crashing?
NSMutableArray *newUrls = [NSMutableArray arrayWithArray: [self urls]];
[newUrls addObject: newurlimadding];
[self setUrls: [NSArray arrayWithArray: newUrl]];
What did you create newUrls for if not to set it as the new value of urls?
Besides that, there are a couple of things you're doing wrong:
No model objects. Bindings hates this. Unless your table view exists solely to display the different parts of the URL (scheme, host, path, etc.), each in one column, you're not giving Bindings what it wants.
Pay attention to the fields in the Bindings Inspector. Note that there are two: Controller Key and Model Key Path. They're exactly what they say on their tins: The Controller Key is the key for a property of the controller, which should provide model objects. The Model Key Path is the key path for one or more properties in the model, which usually should provide value objects, such as strings and numbers.
You probably need to create a model class and make the URL a property of that class. I'd guess that you have other objects, perhaps in parallel arrays, that you can move to properties of the model class. Do that, so that you're working with Bindings instead of against it.
Not using array accessors. You're just setting the whole array at once, which is inefficient and may cause display problems (such as selection highlights disappearing). Implement and use array accessors for this array property. Accessorizer can help you here.
I actually have no idea whether this will fix your crash because you haven't told us anything about it. You should edit your question to include any exception messages or other crash-describing output, which you'll find in the Run Log/Debugger Console.
Also, since the type of urls can be mutable, you should set it to copy, not retain.
NSArray * things; - since this can be modified you better represent using NSMutableArray instead NSArray.
When ever you need to add some new element to the list just use 'addObject' and insert element to the list.
Your binding will make sure that UI is updated using KVO and KVC.
It looks like the problem was that I had NSURLs as my object type. Once I changed the object in my array to a custom-made KVC compliant object, I wasn't getting any more crashes.
Maybe NSURL isn't KVC-compliant on 10.5, but it is on 10.6?