TableView index from rootcontroller to detailcontroller (UINavigationController) - ios

My root view is a grouped tableview. When the user selects a row, i want to be able to retain which row was selected to give to the detailcontroller for loading the correct data.
All the navigation is working fine, I just don't want to have to create a global variable to just retain the index. Is there a built in method for the navcontroller or something?

You can either set a property in you detail view controller before it is pushed giving info about the row selected so it can influence the behaviour of the detail view controller, or it is possible to access the parent view controller directly from the detail view controller with:
#property(nonatomic, readonly) UIViewController *parentViewController
I prefer the first option - you can write a custom init... method, to supply the data for the detail view controller when it's created.
There isn't a builtin way as such, you should try and make the view controllers de-coupled as possible so they can be re-used and are resistent to changes elsewhere in the app.
This is a useful quote from the View Controller Programming Guide for iOS:
With the exception of view controllers managing leaf data, each custom view controller must provide a way for the user to navigate to the next level of the data hierarchy. A view controller that displays a list of items can use taps in a given table cell to display the next level of data. For example, when a user selects a photo album from the top-level list, the Photos application creates a new photo album view controller. The new view controller is initialized with enough information about the album for it to present the relevant photos.

I wanted to follow up with how I ended up coding this. I'm still somewhat new to Obj-C, so some concepts I haven't dealt with or come across, so if this is old hat, sorry.
You can create your data element in the child controller and pass the data 1 for 1 directly to that element by accessing its property.
ParentController.h
NSDictionary *myData;
ChildController.h
NSDictionary *childData;
// This would get called in the parent controller where appropriate
// but before the child controller is presented
ChildController.childData = myData;
This is obviously very stripped down, but the idea works. Just take your data and pass it to the property before calling it and it will be there once the child view is presented. Hope this helps.

Related

Accessing the next object in managedObjectContext from my detailView

I have a simple application that uses Core Data / ManageObjectContext. It works very similar to Apple's sample app. The fetchedResultsController grabs the objects and builds out a table view. When I click it sends the Object at that index to the detail view. Simple.
What I want to do is access the next Object from my current detail view so that I need not return to the table view to move through to the next detail view.
I've seen some similar questions but the answers suggest creating a mutable array which seems to defeat the purpose of core data and managed objects.
Thanks!
Use NSFetchedResultsController
/* Returns the fetched object at a given indexPath.
*/
- (id)objectAtIndexPath:(NSIndexPath *)indexPath;
Note:
Creating a mutable array does not necessarily defeat Core Data nor NSManagedObjectContext, but it definitely would defeat the caching mechanism provided by NSFetchedResultsController.
What you're trying to achieve is to present the same data in a bit different way, so you can use same data source based on NSFetchedResultsController. You can easily get index of passed object so you'll be able to navigate between next/prev objects.
Set up a property that refers to the master view controller on the detail view controller, or make the master view controller a delegate of the detail and make it follow a protocol with a suitable method.
Either way, the master view controller will receive a message from the detail view controller and when an action you specify takes place, you could just set the detailItem again on the detail view controller to the next item in your model.
This is assuming you maintain a reference to the index of the current detail item, and a reference to your detail view controller.

How to store data after popping a storyboard instantiated view controller to then repush it to the navigation controller stack

I have my UIViewControllers mostly setup using a Storyboard file. In some cases I use the usual pattern of a UINavigationController in combination with UITableViewController to let the user dig into configuration details of the application. Each table view cell causes another view controller to be pushed onto the navigation stack (when the cell is selected) and users can go back to the overview table view controller using the navigation controller's back button.
I have the overview UITableViewController and the detail UIViewControllers set up in the Storyboard, including the connections between them using segues.
Most of it works as expected, when I select a table view cell in the overview the correct detail view controller is pushed onto the navigation stack. But if I then change some views in the detail view controller and go back (possibly because I want to look something up)(thus the detail view controller is popped) and then press the same cell again, the views are reset to their original state and the data I put in is lost.
Of course I could save that data in the overview controller when the detail controller is popped and restore it when it is pushed again, but I wonder whether that is the best way.
In the past, I would have constructed the detail view controller myself and stored it in an instance variable. Then, if I had to push it again, I would push the exact same object (not just an instance of the same class) which would mean that it also saved the state of the view.
But as far as I can tell, using Storyboards, for each segue a new view controller is instantiated, so no data is kept. I also cannot set the destinationViewController property of the segue in prepareforSegue:sender: since it is read-only.
Is there a way to reuse an already created view controller in a segue?
Or is there some other elegant way to store the data to reuse it when the detail controller is pushed again? Ideally something the overview table view controller does not have to know about, since it would have to do store the data for all detail view controller in that case.
I know I could retrieve the view controller from the storyboard, instantiate it myself and push it in tableView:didSelectRowAtIndexPath:, but I like the segues and the overview of the view structure the storyboard provides, so I would like to keep that, if possible.
Update:
I think my description was a bit unclear. I do save the data, already, but currently it is saved in the detail view controller (it's not just "saved" by being in the view, I am not trying to abuse the view to store my data), so going back is an implicit "save my current state in this view" in my case. The problem is, I can't implement that in an easy way without storing the data in the overview controller IN ADDITION to storing it in the detail view controller. And I don't want to store it in the overview controller since it is data that belongs to the detail view controller and should be managed by it.
Of course I could save that data in the overview controller when the detail controller is popped and restore it when it is pushed again, but I wonder whether that is the best way.
I think that is the best way. If the detail view controller is being used to edit the data, generally accepted practice is that the user can only leave it by either saving the data or canceling their changes.

Data source for PageViewController - usage of arrays/dictionaries to store view controllers in data source

I am implementing a scroll style page view controller for my app, based on the page based application template.
In the data source class, I am storing the list of view controllers in a dictionary (could also use array I guess) so that I can reuse them if the user swipes back to a view controller they already viewed. There are about 15 total view controllers in the page view controller.
I wonder if this is a good idea compared to calling the story board instantiateViewControllerWithIdentifier each time. (I understand the pageviewcontroller itself stores its own array of view controllers anyway.)
I could instead just store the model object in the dictionary or array and instantiate the view controller and pass in the model object after calling instantiateViewControllerWithIdentifier.
I am interested in what is likely to be the better approach.

Calling multiple views from Uipopovercontroller list view contents

How can I call individual view controllers when I tap each row from my Pop Over List View in the most effective way? Meaning, I don't have to recode to build the Pop Over List View component in each of the individual view controllers, they can sort of share it like a navigation tool.
What I Have Built
I have built the pop over view controller list on my Main View Controller.
This is the 1st view that gets loaded when appDidFinishLaunching is executed.
So, when we run the app, this is what we get:
Link to screenshot of the Pop Over List View:
http://s14.postimage.org/63k567vtd/image.png
For each row in the above Pop Over list, I have a method where I can put in the codes to:
1. Identify which row was selected
2. Based on the row selected, do any action, like NSLog and stuff
3. All this codes sit in the Main View Controller
The Requirement
I am building a demo app, so all data is dummy data at the moment.
I need to call individual View Controller when each of the row in the Pop Over list is tapped.
Each of the View Controllers, will have their own set of data, own set of UI objects, its own XIB file.
So, if user taps on Applications, it must bring up the Applications XIB file and its functionality, followed by any navigations from here. If Application xib has a button that launches another view, this functionality should be in place too.
However, they all must have the same top Navigation Bar with the Pop Over list button, so user can tap that button and see the Pop Over list anytime in the app.
Please share your view.
Thank you.
I suggest looking in to UISplitViewController. It is a component built by Apple to manage what it looks like you are trying to accomplish. Essentially, you set it up with 2 view controllers; the first (called the "master"), would be your table view. The second (called "detail") would be the view controller that gets switched out.
Once you explore it a little and are comfortable with the terminology, here's the general advice:
Inside the master table view controller's didSelectRowAtIndexPath: method, instantiate the appropriate view controller (based on the indexPath), and set it as the detail view controller, like this:
- (void)tableView:tableView didSelectRowAtIndexPath:indexPath {
UIViewController *newDetailVC = // make and configure a new VC based on indexPath
self.splitViewController.viewControllers = [NSArray arrayWithObjects: self, newDetailVC, nil]];
}
Here are the appropriate links:
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UISplitViewController_class/Reference/Reference.html#//apple_ref/occ/cl/UISplitViewController
and further (the later sections of): http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/Introduction/Introduction.html%23

Dismissing a view makes losing it all values... viewWillAppear as a cure?

I have a basic modal view system.
My app loads the UI base in which there are 2 buttons presenting 2 other views.
In those views, a dismiss button.
Everything works fine.
BUT, in one of the 2 modal views, I have a bunch of UISlider & UISwitch.
I want them to retain their values but the dismiss loses them: as soon as I trigger the button to show the view containing the UI elements, this view is shown with all values for all elements as I put initially in the xib.
should I store all values in variables, then in viewWillAppear I could "recall" them ?
would you advice me another strategy ?
Yes, your proposed approach is exactly the right sort of thing. But be careful; viewWillAppear can be called for many reasons; make sure you're only doing this when the view controller is coming into existence and showing the view for the first time.
NSUserDefaults can be an excellent place to store globally needed info like this. In viewWillDisappear, store the desired state info (values of the sliders and switches) in defaults. Then retrieve them the next time the view is about to appear.
When you create the modal view you are creating a new instance of the modalViewController an the modalView. This new instance knows nothing about any other instance. There are a few ways you can retain the information from previous iterations of these modal view controllers.
How I would do it:
Set up place holders in your main view and pass the values that the user selects back to the main view via a protocol and delegate setup. Then when you segue to the modal view you can load those variables in before displaying the modal view.
So let's say you have a dictionary with all of the values: {slider = YES, someValue=10,...} Create that dictionary in the main view controller, the first one that opens, and place some default values in it.
In your modal view controllers create the same dictionary as a property.
Create a protocol in your modal view controller with a method that is something like
- (void) doneEditing:(NSDictionary *)values
Set up your first view as the delegate for the modal view controller and in the implementation of doneEditing copy the values to the dictionary that is present in the first view before popping the modal view.
When the first view is ready to present the modal view again, copy the values to the dictionary property of the modal view before presenting it.
I hope this gets you headed in the right direction. It's important to remember that each time you segue or create and present a modal view you are creating a brand new instance of that view, it knows nothing about the previous instance at all unless you tell it something about it.

Resources