UINavigationController code push to UIViewController not working correctly - ios

I am having an issue when I am pushing to a UIViewController by code from another UIViewController which has the same UINavigationController.
Notes & assumptions:
I created all my UIViewControllers using IB but want to push between them using code.
Both UIViewControllers contain UITableViews: The first to select search criteria & the second to display the results.
"LT" stands for League Table in my class names.
I have three classes in my UINavigation Controller:
LTMasterNavController - of type UINavigationController - owns the properties & results across all the subsequent view controllers. LTResultsViewController retrieved the results from here once LTOverviewViewController has generated them.
LTOverviewViewController - of type UIViewController containing a UITableView. Used to select the filters to be displayed in LTResultsViewController.
LTResultsViewController - of type UIViewControllercontaining a UITableView. Used to display the results from the LTOverviewViewController
Please find my code on the Dropbox link below:
https://www.dropbox.com/sh/9m37y4f1gws99lf/VGNloaLSVO
When the "Show League Table" button is pushed in LTOverviewViewController I want the program to get the results from the filters & then immediately push to the LTResultsViewController.
With this code it pushes to the LTResultsViewController however the view appears to contain nothing. It is black with no UITable View & you cannot select anything.
In testing/debugging I created another button in LTOverviewViewController called "Push to Results" and connected it to LTResultsViewController as a push action in IB. It worked perfectly then when pushing the "Show League Table" button and then the "Push to Results" button, however I want it to happen without user having push that second button. Been stuck on this for days now so any help would be greatly appreciated!
Many thanks,
James

With storyboards and segues this is fairly simple. In the storyboard, click on the connection between the UIViewController you want to transfer data between, I guess between LTOverviewViewController and LTResultsViewController, and give the segue an identifier name: say ResultsSegue.
Now, in the LTOverViewController, you need to implement this method:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
In this method you will identify the segue name and the destinationViewController and pass the data you want the new view controller to have. Here is an example:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ResultsSegue"])
{
LTResultsViewController *viewController = [segue destinationViewController];
[viewController setData:self.data];
}
}
When the storyboard wants to use this particular segue, this method will be called and executed before moving on to the new viewController.

Related

Creating a central log out view controller in storyboard

I am working with Parse, and one thing I have implemented in my app is their built in PFLogInViewController. This controller will be presented at two times in the application - when the app first starts and the user is not logged in, and when the user taps the "Log out" button of my application (logging out takes them back to the PFLogInViewController, as you are required to sign in to use the app). I would like to set this up using Storyboard, as that is how the rest of my app is laid out. How could I set up a central view controller (a PFLogInViewController) that is accessed at these two times? I have already Subclassed PFLogInViewController and set it up, I just need advice on how to place it in Storyboard and how to connect it to my views. To make this question help as many people as possible, the general theme of my question is how does one establish a central Login/ViewController that can be accessed at different points in the application using Storyboard. Attached is the basic idea of what I'm trying to accomplish. I haven't been able to successfully segue to the initial TabBarController, and I'm not sure how I should make the LoginController the initial ViewController if I can't segue. I am programming in Swift, if it matters.
There are a few ways to do this depending upon your application. One way is drop a UIViewController onto the storyboard, but don't wire it up to anything (no segue). Create a storyboard id for it such as "MyLoginVC". Do the necessary subclassing of UIViewController and attach the class to your VC. Then, when you want to display the VC simply do the following or wire this up to your logout button
id destinationVC = [self.storyboard instantiateViewControllerWithIdentifier:#"MyLoginVC"];
[self.navigationController pushViewController:destinationVC animated:YES];
In addition, if you want to show the login VC as the very first VC when you launch your app, then perhaps in your AppDelegate
// Load Root view controller
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
self.rootVC = [storyboard instantiateInitialViewController];
self.window.rootViewController = _rootVC;
[self.window makeKeyAndVisible];
// Load Login view controller
id initialVC = [storyboard instantiateViewControllerWithIdentifier:#"MyLoginVC"];
[initialVC setModalPresentationStyle:UIModalPresentationFullScreen];
[_rootVC presentModalViewController:initialVC animated:NO];
When you finish with your login VC (i.e. successful login) then within login VC
[self dismissViewControllerAnimated:NO completion:nil];
and alternatively instantiate your first VC with something similar to the following from within login VC. Note, since you loaded the root VC above first, it is already there with the login VC sitting over it. When you dismiss login VC, the underlying root VC should be ready to rock and roll. Otherwise you can do the following:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
RootTabBarController *tbController = (RootTabBarController *)[self.storyboard instantiateViewControllerWithIdentifier:#"rootTabBarController"];
[self presentViewController:tbController animated:YES completion:NULL];
}
I think what you want is an unwind segue. Here are the instructions I follow for an unwind segue: https://github.com/bradley/iOSUnwindSegueProgramatically
If the link dies, here is what it said:
In your storyboard create two view controllers.
Subclass UIViewController twice, once for each of the view controllers in your storyboard.
Connect these view controllers to the view controllers in your storyboard.
Make a segue between the first view controller and the second by control+dragging from the first to the second.
Click on the segue you created and give it an identifier in the attributes inspector.
Make a button on the first view controller and link it to an IBAction in its UIViewController subclass.
When this button is pressed, the second storyboard should appear. To make this happen (we are doing it programatically) put the following into the implementation of the action you just created:
[self performSegueWithIdentifier:#"nameOfTheSegueBetweenOneAndTwo" sender:self];
Create a second method in the implemention of the first view controller with the following:
- (IBAction)returnToStepOne:(UIStoryboardSegue *)segue {
NSLog(#"And now we are back.");
}
This method will work to unwind any view controller back to this view controller. Notice that we implement the method in the view controller we wish to return to.
Go back to the storyboard. Focus in on the second view controller. If it is active, you should see a dark bar beneath it with 3 symbols on it. One of these is orange and when hovered over will show the name of the UIViewController subclass that this view controller represents. Control drag from this symbol woth the green symbol that means 'Exit'. You should see all available segue unwinds, which XCode automatically enumerates when you create segue unwind implementations inside UIViewController subclasses that you have shown on your stroryboard. Hence, you should see the segue 'returnToStepOne' as an option. Select it.
In your storyboard's document outline, find the section for the second view controller. You should see an item listed below it with a grey symbol that says something like "Unwind segue from ... to Exit." Click on this item.
Important and easily missed step follows!
On the right side of your storyboard, in the attributes inspector, you should see two fields. One for 'Identifier' and one for 'Action'. In most cases, the 'Action' field will have the text 'returnToStepOne:', which is what we want, but the 'Identifier' field will be blank. Fill this field with the text: 'returnToStepOne' (note that we leave out the colon).
Create a button on the second view controller and link it to an IBAction in its UIViewController subclass.
In the implementation for the method you just created, put the following code:
[self performSegueWithIdentifier:#"returnToStepOne" sender:self];
Run the application. You should now be able to unwind from the second view controller to the first.

How to use segue to pass taken photo

I want to pass a photo taken in the first view controller to a second view controller. I want the user to take the photo in the first view controller and then crop in in the second view controller and then save.. So its like.. User take photo→crop→save. I just want to do this simple task but taking me days to get the segue go right.. Is segue the best way to do this? or is there a more easier way to do this task. I am a beginner in objective -c so its making me confused with segues and all the stuff.
You need to implement prepareForSegue:sender: in the source view controller. This will give you access to the destinationViewController via the passed storyboard. Then you can set the image so its available when the destination view controller is displayed.
As far as segue is concerned you need to create a segue arrow using storyboard by dragging arrow from first view controller to second view controller, and most importantly you need to give the segue an identifier or name.
For firing you segue you may do it programatically, like:
[self performSegueWithIdentifier:#"ShowSecondScreen" sender:self];
For handling things when segue is fired you need to write prepareForSegue() method, you may pass any object from current viewController to next viewController:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ShowSecondScreen"])
{
SecondViewController *secondViewController = segue.destinationViewController;
secondViewController.imageObj = image;
}
}

Creating an array of view controllers?

I'm brand new when it comes to app development so this might be a stupid question.
So i have made a UI table. It is customizable, as in users can insert or delete rows. I want to allow users to click on a table cell and it'll direct them to another view controller. All the view controllers will look the same for each cell (sorta like a template). Any idea how to implement this using storyboard?
Appreciate it!
You do not need an array of view controllers. All you need is one view controller, which gets instantiated when the user clicks the cell to navigate to it, and gets deallocated as soon as the user closes the screen to go back to your main view controller.
All you need to implement this in your storyboard is adding a push segue from a cell or a button in your main view controller to your "detail" view controller. When the segue gets triggerred, your code gets a chance to configure the newly created "detail" view controller in the prepareForSegue:sender: method, before the controller's view appears on the screen. This is the place where you customize the data that shows up in the detail view (presumably, depending on the particular row in the table that has triggered the segue).
Here is a link to a good tutorial explaining how to build a master-detail application with Xcode and storyboards.
In storyboard you create a viewcontroller that will display the data after a cell has been selected, you will only need one and not an array. Link it from the tableviewcontroller to the new viewcontroller. Click the segue in Xcode and in the inspector give it a unique identifier.
tableView:didSelectRowAtIndexPath: will get called when you select a cell, here you can perform the segue:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.selectedObject = ... // store the object that was selected
[self performSegueWithIdentifier:#"mySegue" sender:self];
}
In your tableviewcontroller you make sure you implement prepareForSegue:sender:. Here you can hand over the correct model object to populate your destination viewcontroller with data.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"mySegue"])
{
MyDetailViewCotroller *controller = [segue destinationViewController];
controller.dataObject = self.selectedObject;
}
}
Check out this example code from Apple (does not used Storyboard though): http://developer.apple.com/library/ios/#samplecode/SimpleDrillDown/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007416

iOS Button Handler, segue based on button choice

The kind of design that I'm trying to accomplish in my app currently consists of a navigation controller that is the root controller for another View controller known as Test. Test consists of a UITableView in the top half and an UIImageView in the bottom half. THe navigation bar on the top (which is there as a result of the navigation controller) contains two buttons. The image at the link below ( I don't have the reputation points to post an image directly) should make it very clear.
http://i.imgur.com/GM5eH.png?1
I want my design to be in such a way that depending on which button is pressed the image in the imageview is changed while, though the the text in the table view remains the same, they will transition to completely different screens going forward. To give an example, regardless of which button is tapped my table view will consist of : Option 1, Option 2 and Option 3. However, Option 1 for button A is different from Option B and so on.And, this is where the challenge is for me. I have been able to swap out the images based on the pressing of the button succefully. I did this by using an IBActionNavBarButonPressed and then swapping out the images based on the sender tag. Unfortunately, I don't know how to proceed from here. So for example I have my next couple of screens here. But, how do I set up the segues/transitions in such a way that only Option 1 of choice A goes to a certain screen and so on. From my understanding, I'm looking at a combination of prepareforSegue and the navBarbuttonPress IBAction but I'm still not sure how this would work.
Guys, I'm fairly certain as to what I'm trying to but since I'm new to objective C, I'm not completely sure of how to do it. Essentially, I want the logic to be something like, if(element.selected==0) && (IBActionProvider==1) { performSegueWithIdentifier:#"blah" sender.self]; My issue is whether to put this in the IBAction navBarButtonPressedMethod or to put it in the didSelectRowAtIndexPath method.
Thanks and sorry for the long question!
First you give names to other storyboards views. It contains left hand panel(Storyboard Identifier :).
You should create segue for all buttons and give identifier to it.
Then you should use prepareforSegue like this
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ToContacts"])
{
// Get reference to the destination view controller
ContactVC *targetVC = [segue destinationViewController];
// Pass any objects to the view controller here, like...
targetVC.CompanyNme = selectedRowValue;
}
if ([[segue identifier] isEqualToString:#"ViewCompany"])
{
ContactVC *targetVC = [segue destinationViewController];
targetVC.CompanyNme = selectedRowValue;
}
}
#"ToContacts" means your storyboard identifier.

iOS - How to inject data to view controller displayed within tab bar controller?

I've got an iOS app that has a page view to show multiple items as pages. Each page contains a tab bar controller with 2 tabs so I can show the info for each page in 2 ways - as a table or as a graph. Here's a screenshot:
So the user chooses which item to look at (in this case bananas) by changing pages. But I can't figure out where or how I should inject which item they're looking at into the 2 view controllers within the tab controller. Here's a shot of my storyboard if that helps. I want to inject it when the table view controller or graph controller are created but I can't see where that's happening to get at that code - have I missed something?
Thanks.
Not sure if this will work the same in the storybaord environment, but there is UITabBarControllerDelegate that has a callback method named didSelectViewController. It will give you the viewcontroller that is being selected. Doc from Apple.
If my understanding is correct, you should subclass your tab bar controller and implement the
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
method.
In there you can access the destination view controller by the segue object's destinationViewController property.
Depending on the segue identifier you can customise your destination view controller:
if ([segue.identifier isEqualToString:#"SegueID"]) {
MyViewController *myViewController = (MyViewController *)segue.destinationViewController;
//customize view controller
}

Resources