Xcode Having trouble loading a View via code - iphone

I am working on an iOS app and am having some difficulties. I am using storyboards and have placed a button which is connected modally to launch another view. The button works great. However, the button is really just a placeholder and in reality, I would like some code to launch the new view. I have tried several methods, all of which seemed straightforward but result in nothing happening. Is there a way to have my code activate the segue that my button currently activates?

I think #ctrahey 's solution should work. Try dragging the segue from the source view controller (not the button, but the vc that contains it) to the destination view controller and be sure to set it's type to modal.
I think sender == self vs. nil shouldn't matter in this case.
However, if that doesn't work, my usual practice for modal vcs is to not draw any segues to them in IB. Instead, I let the modal VC float in IB with no connections, giving it an "Identifier" on the attributes inspector. Then I use code like this:
// be sure to use the real name of your storyboard
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
// use the identifier you assigned to the modal vc
MyModalViewController *newVC = [storyboard instantiateViewControllerWithIdentifier:#"MyModalViewController"];
// presentingVC might be self, if this code is inside a vc
[presentingVC presentModalViewController:newVC animated:YES];

Give your segue an identifier (in the right-hand inspector panel), then in a view controller (from the same storyboard) do:
[self performSegueWithIdentifier:#"YourSeguesIdentifier" sender:self];

Related

Warning: Attempt to present <CustomViewController> on <UINavigationontroller> whose view is not in the window hierarchy

I know this has been asked a million times, but I couldn't find a suitable answer in those many questions that I've examined.
I have a custom view controller, and I'm trying to display the view controller when the user taps a button (so no "infamous viewDidLoad problem" here).
Here is my code that runs when the user taps the button: (I have the NIB for the view controller, and I have a navigation controller)
ICLoginViewController *loginViewController = [[ICLoginViewController alloc] initWithNibName:#"ICLoginViewController" bundle:[NSBundle mainBundle]];
//assuming we have a navigation controller.
UINavigationController *navigationController= (UINavigationController*)[[UIApplication sharedApplication] keyWindow].rootViewController;
[navigationController.topViewController presentViewController:loginViewController animated:YES completion:nil];
I'm getting the Warning: Attempt to present <ICLoginViewController: 0xa08a810> on <UINavigationController: 0xa45de70> whose view is not in the window hierarchy! error when I try to present the view controller. Nothing happens on screen. If I tap multiple times I get the same error, and still nothing happens. I've set a breakpoint and verified that navigationController and navigationController.topViewController are not nil. I' using storyboard (if it helps) but not for the custom view controller that I'm trying to display. (I want to make it an app-independent library in the long run, so I'm not referencing any app-specific modules within) Why am I getting this error?
I've found the solution. The problem was, my modally displayed view controller was not the 'top' view controller in navigation controller. If I change the calling view controller to be pushed instead of being modal, then it becomes the top view controller and my app works well. Apparently, this had nothing to do with my custom view controller, but my navigation stack.
If its in an NSObject create a method inside the NSObject that takes your current viewController as an argument and present it there.
eg:
-(void)presentInViewController:(UIViewController *)controller{
ICLoginViewController *loginViewController = [[ICLoginViewController alloc] initWithNibName:#"ICLoginViewController" bundle:[NSBundle mainBundle]];
[controller presentViewController:loginViewController animated:YES completion:^(BOOL comp){}];
}
This way you can call that view controller wherever you want instead of trying to find your way through the navigation stack from UIApplication.

Navigation bar not visible when manual segue

I have a little problem with segues in my app. I am trying to manual PUSH segue. But navigation item/controller/bar is not visible on target controller. When i use button and segue with that button to target view controller, navigation bar IS visible :/
My code is simple:
[self performSegueWithIdentifier:#"MySegue" sender:self];
MySegue is push segue from root view controller of UINavigationController to target controller.
It even did not work with this one
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Storyboard" bundle:[NSBundle mainBundle]];
UIViewController *controller = [storyboard instantiateViewControllerWithIdentifier:#"TargetViewController"];
[self.navigationController pushViewController:controller animated:YES];
and even if i set top bar (navigation item) in story board manualy
thanks for any help:)
Delete the segue that goes from StaznostiViewController to StaznostViewController. Control-drag from the StaznostiViewController object (in the bar below the view) to the StaznostViewController, NOT from the StaznostiViewController view or from the StaznostiViewController tableview prototype cell. Select Push style. Name your segue whatever you wish.
In your code, in the target-action method that you have defined for your dynamic button(s), this is where you call the method performSegueWithIdentifier.
Also, make sure that in the properties for StaznostViewController, you have the property for Top Bar set to Inferred.
Same thing happened to me. I created a "Push" segue from storyboard, and was calling it from code. Then it lost navigation items on the navigation bar. When I changed the segue to "Modal", then navigation items of the destination view appeared properly. .
try nil sender instead of self:
[self performSegueWithIdentifier:#"MySegue" sender:nil];
hope it works

Accessing UINavigationController at Top of Stack

How do I get a reference to the UINavigationController's backBarButtonItem from the UINavigationController at the top of the stack. In some circumstances I want to disable going back until some networking code is complete.
self.parentViewController.navigationItem.backBarButtonItem.target =
self;
self.parentViewController.navigationItem.backBarButtonItem.action =
#sel...;
doesn't work
delegate method
- (BOOL)navigationBar:(UINavigationBar *)navigationBar
shouldPopItem:(UINavigationItem *)item
doesn't work either.
An answer and a recommendation:
The answer: I would recommend you change your MVC model slightly to have a BOOL property in your model that is on or off depending on whether the network activity is done and then use a delegate/protocol adopted by your QuestionsVC that updates the back button setting as that property changes. You would need to add the following in the delegate method in QuestionsVC:
[self.tabBarController.navigationItem setHidesBackButton:YES animated:YES];
I tested it and it works.
The recommendation: It is never recommended to have UITabBarController inside a UINavigationController (only the inverse is recommended). I would adjust accordingly before you get too deep into your project.
Update:
I can understand the need for a mainVC as startup VC with a button to "start" if you will. You are correct that you need a NavController to be able to push/pop VCs and use segues in Storyboard. But that is not the only way to display a sequence of VCs, you can present/dismiss VCs. So in your case:
1- I would delete the first NavController
2- Make the MainVC the starting VC (entry point) by moving the arrow on the left of the NavController to the left of MainVC
3- Disconnect Main VC from TabBar controller (delete that link) because you will not be able to use segues in SB without Nav Controller. You will have to instantiate and present that tab bar Controller.
4- Add a new object file (.m/.h) - a subclass of UITabBarController and change the class of the tabBarController in IB to the name of your subclass. You might have to build/clean or restart xcode if it does not show on the dropdown of the class list in IB.
5- Create an IBAction method in your mainVC and link it to the button in Main VC.
6- In that method (in your Main VC), add the following code:
yourTabBarControllerSubClassName* myTabController= [self.storyboard instantiateViewControllerWithIdentifier:#"theTab"];
[self presentViewController:myTabController animated:YES completion:nil];
7- Make sure that in your SB that you select the tab bar controller and in the identity inspector, put the SB ID as "theTab" and check "use SB ID".
8- if questions VC or status table VC have a sequence of VCs within each, you can embed each VC in a Nav Controller and that would be ok.
With that the case, you might not need to worry about that back button since it won't exist anymore!
Good luck
Hope this helps.

Pushing UINavigationController into UIViewController Using Storyboard

My app's storyboard is using UIViewController's to go to different views of the app. However, I want to try a third party library, that is EGOPhotoViewer, not to reinvent the wheel. But how do I add UINavigationController to UIViewController from the storyboard? Here is the code this library is using to initialize.
EGOPhotoViewController *photoController = [[EGOPhotoViewController alloc] initWithPhotoSource:source];
[self.navigationController pushViewController:photoController animated:YES]
It only works for me when I add it as a view controller:
[self presentModalViewController:photoController animated:YES];
but the library works best within navigation controller because title bars and navigation buttons are missing from my testing approach.
In the storyboard
select your original viewController, then in the menu:
Editor -> embed in -> Navigation Controller (that viewController becomes the rootViewController)
Now you have various options to push your photoController eg:
From a UI widget in your rootViewController, CTRL-drag to photoController. That will create a segue which should work without extra code (although it helps to name the segue so that you can refer to it later in code)
or in code as you have in the question.

How to add ViewController on top of tabBarViewcontroller using storyboard?

In my application i want to add a viewcontroller with nib on top of tabbarviewcontroller using storyboard.
for eg; when the application launch for first time i want to show that view controller for once and after that when ever user start the application it should show the tabbarviewcontroller. and not the viewcontroller.
following is my code
-(void)viewDidAppear:(BOOL)animated
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateInitialViewController];
[vc setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentModalViewController:vc animated:YES];
}
I'm a little confused with how you described what you want. There are a couple of ways to do what you want and depending on how you want things to flow.
Storyboard
If you stay in the storyboard, you can add a UIViewController - in front of your tabbar (to the left of) controller. Basically, add a UIViewController and move the start arrow to it. then create a segue from it to your tabbar controller. You can bring in the tabbar controller via a push segue or even as a modal segue if you want.
You would have to move your xib file into the storyboard.
It would flow like this: UIViewController -> UITabbarController -> Rest of your app.
In this model, the first view controller would always be available on launch.
Another strategy - trying to keep things simple is to use the first view controller attached to the tabbar. It would align with the left most tab.
That view controller gets instantiated and put on screen by the tabbar controller first under normal conditions. You can add code in that UIViewController in the ViewDidLoad or ViewDidAppear methods to instantiate and put up the modal view using either a storyboard or a nib file.
Finally, the last way I can think of would be to load the nib file from your app delegate then display your tabbar from the storybook as a modal. I think this approach is the least desirable, but doable.
hope that helps. good luck.