Call another ViewController without using storyboard - ios

I changed my button from calling another ViewController from Storyboard to download some stuff from a website using JSon. Now I need to call the very same ViewController after the code...
probably it is a simple stuff but I didn't quite get it
thanks

I am not sure that this is what you are looking for, but look at this.
Let's say you have two controllers, ViewController1 and ViewController2. After you are done with the JSON parsing in ViewController 1, let's say from [self finishedGetJSON], you could do this;
- (void) finishedGetJSON(yourargument*) arg {
ViewController1 * screen = [self.storyboard instantiateViewControllerWithIdentifier:#"yourIdentifier"];
[self.navigationController pushViewController:screen animated:YES];
Is that what you were looking for?

Related

using self.navigationController.view in another class Xcode

I'm currently using MRProgress in my project. Before time, I've put these two libraries in every files of my project. At that time, MRProgress working well and show correctly display in this project. Now I'm creating common class and put all of functions into that class to make reusable and optimize my project like that.
common.m
- (void) myFuntion:(UIViewController *)myvc {
[MRProgressOverlayView showOverlayAddedTo:myvc.navigationController.view animated:YES];
..
..
..
..
[MRProgressOverlayView dismissOverlayForView:myvc.navigationController.view animated:YES];
}
myusage.m
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"stb" bundle:nil];
ViewController *searchVC = [storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
[common myFuntion:searchVC];
At that time, my problem is MRProgress cannot display anymore. Please let me know what I did wrong.
First, verify if ViewController is embedded into a navigation controller
You can put a breakpoint and then 'po searchVC.navigationController' in the console
Btw, I don't know if you did it wrong or not, but it doesn't make sense to add MRProgress on the navigationController and then dismiss it with 'self.view'. You should dismiss the same view you added the overlay, in your example it should be : myvc.navigationController.view
From above shared code it appears like you have declared instance level method:
- (void) myFuntion:(UIViewController *)myvc
And you are calling it like class level method, try replacing above prototype with following
+ (void) myFuntion:(UIViewController *)mivc
Actually methods that are declared with "-" are treated as instance level and functions with "+" are class level.
Reference: http://rypress.com/tutorials/objective-c/classes
Use this method after pushing view like :
SceondViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"SceondViewController"];
[self.navigationController pushViewController:controller animated:YES];
[self myFuntion:controller];
Hope it will useful for you.

Programatically return to previous ViewController in different storyboard

I tried many answers here but none of them had the same exact scenario.
I'm trying to navigate to a UIViewController that's within a separated storyboard in a different bundle, so far I was able to navigate to it but am unable to return to the previous UIViewController. The method that invokes the external view controller (TabBarController) is implemented as follows:
+(void) launchExternalUI: (UIViewController *) previousViewController {
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: [self frameworkBundle]];
TabBarController *vc = (TabBarController*) [sb instantiateInitialViewController];
[previousViewController.navigationController pushViewController:vc animated:YES];
[vc release];
}
Now the method within TabBarController that should return to the previous view controller:
- (void) navigateToPreviousViewController: (UIGestureRecognizer *)gesture {
[self.navigationController popViewControllerAnimated:YES];
}
In TabBarController, if I print all the viewcontrollers within self.navigationController, all I see is the TabBarController, shouldn't I see the previous view controller that pushed this on launchExternalUI ? The [self.navigationController popViewControllerAnimated:YES]; has no effect at all. I'm a bit lost on this.
It's also important to notice that previousViewController is defined in a local storyboard and TabBarController is implemented in a different .framework, would that cause the issue?
Thanks in advance for all the help!
**Edit: The navigation flow I need is storyboard1:VC1->storyboard2:VC2->storyboard1:VC1, I can get storyboard1:VC1->storyboard2:VC2 part to work but not storyboard2:VC2->storyboard1:VC1
I often split projects up into various Storyboards, and have created a dynamic view controller that handles the task of loading the appropriate controller from a secondary storyboard, whilst maintaining the navigation tree.
I've created a sample project and uploaded to github as it's easier than explaining all the steps here. The key part to note is the User Defined Runtime Attributes for each of the DynamicStoryboardViewControllers in the Main.stoyboard. Note also that each of the secondary storyboards need the "is initial View Controller" checked for one of your viewControllers. Not included in the example is loading a specific scene from a storyboard. This is no more than adding the "sceneName" dynamic runtime attribute much in the same way as the storyboardName attribute is added.
it's a quick sample so a little rough, but you'll get the idea of how it all works. Feel free to ask questions if you get stuck.
Cheers!
EDIT:
It dawned on me that perhaps you don't have a navigationController in the view hierarchy (as i do in my sample). And in any event, seemingly, you won't have much control over where your tab bar is introduces. So without a navigationController the [self.navigationController popViewControllerAnimated:YES] won't work;
You should test for this and either call the popViewControllerAnimated as you do, or call dismissViewControllerAnimated ;
if(self.navigationController){
[self.navigationController popViewControllerAnimated:YES];
}else{
[self.presentingViewController dismissViewControllerAnimated:Yes completion:nil];
}
Hope this helps, if not, perhaps you can supply some sample code.
Create an unwind segue within your original view controller, and use segues instead of pushing/popping view controller views onto the view array.
To create an unwind segue you should create an unwind method in the ORIGINAL viewcontroller:
- (IBAction)unwindToOriginalViewControllerSegue:(UIStoryboardSegue*)sender {
; //TODO: anything special you need, reference via sender
}
Then, in your NEW viewcontroller, in the storyboard, drag from the controller icon to the Exit icon. Link that to the Unwind segue you named above.
UIViewController * YourViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Storyboard Identifier"];
[self.navigationController pushViewController:YourViewController animated:TRUE];

UINavigationController back button return to FIrstTableViewController

So I was create three UITableViewControllers with UINavigationController. I want a back button on 3rd UITableViewController, what returns my view to first UITableViewController instead of second.
How can I do that? That must be a real backButton, not a image or something else. Will be perfect to do this only with storyboard.
UPDATE
Perhaps I poorly explained what I want.
I don't want use any button with action on it. I just want something like as setting "address" of 1st TableViewController on my default back button. There is any way to do it?
add a button and connect it to following action
- (IBAction)backToFirstView:(UIButton *)sender
{
[self.navigationController popToRootViewControllerAnimated:YES];
(or)
[self.navigationController popToViewController:yourFirstViewControllerObject animated:YES];
}
There are different ways to navigate from DetailViewController to other view controllers.
We will go through the cases one by one.
First of all I would like to clear that if its your default
navigation bar's back button, then it must return to the last most
view controller only which is actually a default behavior of a
navigation controller.
Second, If you would like to go back to the
last most view controller on the tap of a button placed by you, you
should write the following code
[self.navigationController popToViewController:NAME_OF_A_VIEWCONTROLLER animated:YES];
Third, If you would like to go to the first view controller from where you
started, you should write the following code
[self.navigationController popToRootViewControllerAnimated:YES];
Ok, I found a way to resolve my problem. Thanks for your answers guys, they was very helpful.
So for resolve this problem you just need use link what give me Kumar KL upper, and wrote next method in your UITableVIewController
-(void) viewWillDisappear:(BOOL)animated {
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
// Navigation button was pressed. Do some stuff
[self.navigationController popViewControllerAnimated:NO];
}
[super viewWillDisappear:animated];
}
Now you got a backButton what redirect you to your viewController, BUT title of this button is wrong. Let's resolve that unfair.
Create new class CustomSegueцрфе inherited from UIStoryboardSegue with next code in CustomSegue.m :
- (void)perform
{
UIViewController *sourceView = (UIViewController *) self.sourceViewController;
UIViewController *destinationView = (UIViewController *) self.destinationViewController;
[[destinationView navigationItem] setTitle:#"TitleOfYourViewController" ] ;
[sourceView.navigationItem setTitle:#"TitleOfButton"] ;
[sourceView.navigationController pushViewController:destinationView animated:YES];
}
Now you can go to storyboard and connect 2nd ViewController with 3rd with custom segue.
Like you see UINavigationController uses Title of previous ViewController for button title, so you just need change it.

pop To View Controller

I am new to coding objective-C and am trying to use pop to viewController. To do this when a button is tapped i use
[self.navigationController popToViewController:(what goes here) animated:YES];
I know its a UIViewController* that goes there but I am wondering where do I declare this and what code would I use to declare it.
My basic storyboard is I have 4 view controller A,B,C,D and A is the root which pushed to B which pushes to C which pushes to D, my button is on D and I am trying to pop back to B. The object at index method won't work because its doesn't always go A->B->C->D sometimes it goes A->C->B->D so
[self.navigationController popToViewController: [self.navigationController.viewControllers objectAtIndex:2] animated:YES];
So that doesn't work.
Thanks for the help in advance. Sorry if this question is too basic.
You need a way to find the desired view controller to pop to.
-(IBAction)popToDesiredViewController:(id)sender
{
UIViewController *desiredVC = nil;
// LOOK AT ALL VIEW CONTROLLERS IN NAVIGATION CONTROLLER
for (UIViewController *oneVC in self.navigationController.viewControllers) {
// CHECK IF THIS IS THE VIEW CONTROLLER YOU WANT
// change this to your logic
BOOL foundDesiredVC = [oneVC isKindOfClass: [SignInVC class]];
if (foundDesiredVC) {
desiredVC = oneVC;
break;
}
}
[self.navigationController popToViewController:desiredVC animated:YES];
}
Personally I don't find this as a basic question, even I got struck in such a situation. But I found a good solution by using “Mediator Design pattern” and develop my custom UINavigationController as a coordinator by combining the method:
- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated
and maintaining my own navigation stack.
A coordinator (your custom UINavigationController) has to have the control over your navigation, if your are having unpredictable way of navigation.

instantiateViewControllerWithIdentifier and pass data

I am using Storyboard in my app and I want to pass data from one view to another view.
Instead of using segues I am using instantiateViewControllerWithIdentifier. In this case I am instantiate from my first TableViewController to a NavigationController which has a second TableViewController attached because I need the navigation in the second TableViewController. Now I want to pass data from my first TableviewController, depending which row was clicked, to my second TableviewController. In this case newTopViewController would be my NavigationController but my problem is now how to pass data from firstTableViewController to the secondTableviewController.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *identifier = [NSString stringWithFormat:#"%#Top", [menuArray objectAtIndex:indexPath.row]];
UIViewController *newTopViewController = [self.storyboard instantiateViewControllerWithIdentifier:identifier];
}
If you instantiate a navigationController, you can use the viewControllers property to get the inner viewController of the navigation controller.
Something like this:
UINavigationController *navigationController = [self.storyboard instantiateViewControllerWithIdentifier:identifier];
MBFancyViewController *viewController = navigationController.viewControllers[0];
// setup "inner" view controller
viewController.foo = bar;
[self presentViewController:navigationController animated:YES completion:nil];
newTopViewController.anyVariableToShow= anyVariableToSend;
I do this pretty often on a few of my apps...
//Create new VC
CookViewController *detailViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"CookVC"];
//Set recipe
[detailViewController setRecipe:recipe];
//Pop over VC (can be pushed with a nav controller)
[self presentPopupViewController:detailViewController animationType:MJPopupViewAnimationFade];
If you aren't using a navigation controller or segues, then I think you need to reconsider your app design.
Actually it's not just a data pass problem as this is a program control and data transfer question together.
Even you would have to rethink about your app's concept, as you'd like to use storyboard without the meaning of storyboard, it's up to you and I hope you have good reason to do what you do.
So when you decided not to use segue you lost the new and comfortable way of instantiating a new controller and transferring data with it and you have to do the transfer of control and the data in two distinct steps. When you instantiate another scene in storyboard (like you do with instantiateViewControllerWithIdentifier:) you just instantiated a new controller and transferred the control but not the data. Just think about it as you instantiated a new controller from a xib in an old way (so you have to use initWithCoder: or awakeFromNib in the second view controller as the storyboard will not call initWithName:bundle:), but did not do anything more.
So you will have a new controller (it named in the identity part of the second storyboard) which is hanging in the universe without any relationship or connection with anything else (as the storyboard picture illustrates it nicely) and you could do with it what you'd like.
So you'd like to do something and you need data from the previous storyboard (ViewController). What you need is making available those data to the second storyboard(ViewController), and as you know there are lot of solution for this which were available long time before even storyboard is existed.
So regarding your code, the "data transfer" is depending on your design, whether the two controllers are subclasses of each other or whatsoever...
If you don't like to deal with subclassing and like to decoupling them as much as possible, the best way just make a property of your data in the first controller and refer to them from the second (after importing the first's .h file) and just refer to it in it's viewDidLoad or in initWithCoder: or anywhere where you need them, as
secondViewControllerdata = firstViewControllerdata.thatDataProperty
Of course you can do the same in reverse and make a property of the second controller and refer to it in your first view controller.
You can define some parameter in UIViewController to receive data:
#property (assign) int param1;
#property (retain) NSMutableArray *param2;
and use below to pass the data:
[newTopViewController setParam1:XX];
[newTopViewController setParam2:XX];

Resources