passing data in nsmutabledictionary from child view to parent view - objective-c

I have parent view and child view.In child view i have a NSMutableDictionary .and i add values on it.then go back to parent view and want to get values that I added in child view, any one can describe with code. any idea??

The iVars are only accessible while the view is in the run loop.
If it gets deallocated the iVar will be deallocated as well.
There are numerous ways to achieve what you are trying at.
One approach is to store global variables in your App Delegate, which are accessible through all views and the entire application run.
Another approach is, if you don't need the variable to be global accessible to use the NSNotificationCenter and subscribe for a notification.
The second approach is explained in this SO answer by me
Basically you can pass any value to the userInfo, so in your case you would be passing your Dictionary, this way:
[[NSNotificationCenter defaultCenter] postNotificationName:#"myNotification" object:self userInfo:MyDictionary];

create property in parentView.
And in child view code like below.
((parentView*)childView.superView).dic = dic;
may it help you.

Create an object for "ChildView" in "ParentView", then use the child object to access the NSMutableDictionary.
e.g:
//ParentViewController.m
ChildViewController *cvc = [[ChildViewController alloc]init];
NSDictionary *dict = cvc.myDict;

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];

NSManagedObject without values

Im passing a NSManagedObject to a UIView. So Im showing a UITableView of meetings brought from CoreData, if you tap on one of the meetings you will be able to see, on another view, more info of that meeting, info that is contained in a NSManagedObject. I want to pass that NSManagedObject to the view that will show its info.
So I created a init method of that view like this:
-(id)initWithMeeting:(NSManagedObject *)aMeeting{
_theMeeting = aMeeting;
return self;
}
Then I use the info in the _theMeeting object to show it in the view that I just created in the ViewDidLoad. The problem is that whenever I try to access any of the values of the NSManagedObject it crashes, it has values in the init but not in the ViewDidLoad.
I believe it has something to do with the Managed Oriented Context, but the Managed Oriented Context never disspears, is an attribute of the AppDelegate.
So I dont know how to pass that Object and keep it.
I also declared theMeeting:
#property(nonatomic, copy)NSManagedObject *theMeeting;
Hope you can help me.
Are you using the accessor to assign theMeeting? I think you're just bypassing it so aMeeting is not retained or copied, and therefore the crash.

Saving UIViewController in appDelegate

I am using Xcode 4.3 and need to know the parent view controller of the current view.
I am also using storyboard.
self.parentViewController always returns nil.
I saw different answers to save the parent view controller in AppDelegate class as a property. E.g., To create a variable: UIViewController parentViewController in AppDelegate and in the code write:
appDelegate.parentViewController = self;
I am afraid that it will consume memory - as this is a heavy object.
What is the best approach to know aretnViewController when using story board?
Whether or not an object is "heavy" does not matter as long as you store only a reference to it (in your case in the application delegate). Creating a second object would make a difference, but the line
appDelegate.parentViewController = self;
does not do that, it merely stores a reference to the object.
I know that this does not answer your direct question, but I think you should go ahead with the "store a reference in the app delegate" approach.

Navigate to a specific UIViewController after receiving a NSNotification

I am developing an iOS application that handles a hierarchy of UIViewController objects using a UINavigationController:
MenuViewController
|
|-ListOfAnimalsViewController
|
|-AnimalDetailsViewController
|
|-ListOfPlantsViewController
|
|-PlantDetailsViewController
The application receives local NSNotification objects with information of a certain animal or plant. The usual behavior when you touch the notification is to open the application and load the first view controller in hierarchy.
Is there a way of programmatically navigating to an instance of a UIViewController deep in the hierarchy instead?
EDIT: I am not asking for pushing the controller into the navigation stack, but for pushing the previous controllers as well, i.e. I would like to keep the navigation schema above.
I'm gonna have to disagree with Suresh. While this solution may work in a simple case like this where you only have 1 previous ViewController, what if you wanted to add a 10th ViewController and keep the entire hierarchy? First of all you'd have to pass the final piece of data you want to show (in this case the plant or animal) through every ViewController and you'd be creating 10 ViewControllers at once. The transition between the current ViewController and the 10th would be far from seamless, performance would be terrible. Also no need to go and create your own navigation system, no need to make things more complicated than they are since this issue isn't too difficult.
Just push the ViewController you want to show, that way you'll only be creating 1 ViewController. In every ViewController that can be pushed as a result of a notification (and all the ones below that), override the behavior of the back button. Check in the viewControllers property of the navigationController if the ViewController before is is the one you expect, using NSStringFromClass. If not, create an NSMutableArray as a copy of the viewControllers, create the ViewController you do expect and insert it at the second to last spot in the array. Then replace the entire stack by calling the setViewControllers:animated: method on the navigationController with the mutable array, animated NO. Finally do the pop. Again you'll have created just 1 ViewController at a time, keeping your performance optimal.
Ican't post code right now since I'm on an iPad but if you need it, just ask and I'll add an example when i have a real keyboard.
If you know the name of the class you can use the following code to navigate.
NSString *className = #"viewControllerName";
UIViewController* myClass = (UIViewController*)[[NSClassFromString(className) alloc] init];
[self.navigationController pushViewController:myClass animated:YES];
I think you will have to invent your own mechanism for following the navigation order since there's nothing in an iOS view controller's static definition that defines an ordering. (Segues seem to be as close as it gets and that's not very close.)
If I had to do this for a hierarchy of view controllers with some unknown depth, I'd consider creating a superclass that worked with a path, sort of like network routing. It would have a method such as displayNextControllerOnPath:(NSString *)path. A MenuViewController that was a RoutingController subclass would receive a path like #"ListOfAnimalsViewController.AnimalDetailsViewController", strip off the first path element, instantiate it (it being another RoutingController subclass), and send it #"AnimalDetailsViewController".
Other details would involve knowing when to stop and perhaps passing an object or dictionary as a payload for the last controller to use as content.
I would reconstruct the stack in the following way:
MenuViewController *menuController = [[MenuViewController alloc] init];
ListOfAnimalsViewController *listController = [[ListOfAnimalsViewController alloc] init];
AnimalDetailsViewController *detailsController = [[AnimalDetailsViewController alloc] init];
UINavigationController *navigationController = [[UINavigationController alloc] init];
[navigationController setViewControllers:#[menuController, listController, detailsController]];
self.window.rootViewController = navigationController;
You may need to set some properties to based on your implementations.

Adding array from one view to another and retaining values

I have four views, with four arrays. As soon as I navigate from one view, I add that particular array to my master array.
Initially this master array has nothing, and is allocated when the app runs using 'init' method. It does not have a view and it is an array from a subclass of NSObject.
Finally the master array should consist of {viewarray1, viewarray2, viewarray3, viewarray4}.
Each array is added to the master array when navigating to the next view.
So is there anything wrong in my implementation ? Is it okay to allocate masterArray in the init method? Each time I add an object to masterArray, I NSLog it and it displays (null)
How can I have the master array retain values for the whole app??
Some Information on the Code:
I initialize my master array in another class, in the -(init) method
masterArray = [[NSMutableArray alloc] init ];
While adding an object to MasterArray from another view, I reference that class, and I create an object for the class, and add it as a property and synthesize it. I then use
[self.thatClassObject.masterArray addObject:self.viewArray1];
There are two ways you could go about initializing it that I can think of offhand. First, you could alloc/init the array in the app delegate. This will ensure it's created before the rest of the views get a chance to add to it.
EDIT: There's only really one way I can think to do this as Josh Caswell pointed out a good fact that class initializations won't work for this situation. You're best off calling alloc/init for the array either in the app delegate or whichever view is made key window first. You'll have to reference it to the other classes from there