I have a TableViewController that can be transitioned to from two other view controllers; one transitions by segue, and the other programmatically. Everything works well when transitioning via segue, but when the TableViewController appears after a programmatic transition, the UIBarButtonItem is missing and the cell segue doesn't work (it should take the user to a new screen).
I'm guessing that because the UIBarButtonItem and cell segue were setup in the Storyboard, they aren't loaded when the TableViewController is loaded programmatically. So, I'm assuming that I need to load them manually somewhere. My question is where the appropriate place to do this is?
Thanks for reading.
EDIT:
Here's the code for the transition:
OtherTVC *otherTVC=[[OtherTVC alloc] init];
[self.navigationController pushViewController:otherTVC animated:YES];
This is linked to the callout accessory of a map pin.
To get an instance of the controller as it was created in the storyboard, try giving it an identifier and using instantiateViewControllerWithIdentifier: rather than the alloc/init route. If your current controller where the code is running came from the same storyboard, you can get a reference to it through the controller's storyboard property in order to make that call.
Related
I have defined a segue from source tableview controller to another and trying to programmatically transition to the destination controller upon click of a UITableViewCell using the following statement:
[self performSegueWithIdentifier:#"pushToDestinationViewController" sender:self];
However, I find that the segue doesn't result in a "push" to the destination view controller.
On the other hand, if I wire the segue to a specific cell in the source view controller it works.
In addition, if I call the destination viewcontroller programmatically using:
[self showViewController:DestinationViewController] it works.
Can someone advise if this is a known issue in iOS 8 or if I am missing something here.
Did you have a segue in your Storyboard called pushToDestinationViewController? You will need to make sure that you have this segue in your Storyboard first like below.
Or, if you just want to simply push another view controller, you can just use [self.navigationController pushViewController:destinationViewController].
I use three view controllers and on each view controller I put UITableView and UITableViewCell. When I connected from the first view controller's table view cell to another view controller's from within storyboard and ran the simulator, the segue works as expected. However, when I connect from the second view controller's table view cell to the last view controller from within storyboard IN THE EXACTLY SAME WAY as the first one, then for some reasons the transition doesn't work.
If I define didSelectRowAtIndexPath: and within it call [self performSegueWithIdentifier:#"showDetail" sender:self]; in the second view controller's implementation file, the transition can work as expected. I don't care about whether it's storyboard segue or methods defined in my code to perform the transition, as long as the transition does work correctly.
However, I'd still like to know why such inconsistency occurs. As I said, I connected two storyboard in the exactly same way in both cases and checked out attribute inspector and connection inspector, but I don't find any differences between the two connection there.
Also, while the first view controller can perform the transition without the method being defined, when I define it then the transition doesn't work, issuing the following error message:
Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
I think I cannot use both approaches (i.e. storyboard segue and method calls) - I just wanted to know what derives the inconsistency here.
I use iOS 7 and Xcode 5.
First of all, if you use push segues, you can't make a push for the second segue if the first segue is modal (unless you embed your second VC in a navigation controller).
Second, make sure de segue identifiers are unique for each segue.
If you ctrl+drag a segue in storyboard, don't call performsegue in code, you just attempt to do the same operation twice. If the segue is in storyboard, in code you should use prepareforsegue delegate.
Another way of doing all of this is not using any segue in storyboard, then in code #didselectrowatindexpath you can instantiate your destination vc using [storyboard instantiateviewcontrolerwithidentifier...], then [self.navigationcontroller pushviewcontroller..] for a push segue or [self presentviewcontroller...] for a modal.
EDIT: Also, when you ctrl+drag, make sure you are dragging from the cell and not from the table.
Self Answer
I finally found out that the issue was not caused in storyboard - it's on the implementation code. Since I have to use UITableViewCellStyleValue1, I cannot use dequeueReusableCellWithIdentifier, and for some reasons the dequeueReusableCellWithIdentifier has to be used in order to make an automatic transition from cell to another view controller from within storyboard only. I checked out that using dequeueReusableCellWithIdentifier and disabling UITableViewCellStyleValue1 temporarily makes it successful to make the transition without didSelectRowAtIndexPath: method being defined.
I'm running into trouble with what I think is a pretty basic task. Within peoplePickerNavigationController:peoplePicker:shouldContinueAfterSelectingPerson: i want to show my own view rather than the standard person view. I'm using a Storyboard, but don't think I can simply manually segue to a window here so I'm thinking I need to create a new XIB with a View Controller in it. I'm setting the Class of the View Controller to my custom View Controller in IB. Then in peoplePickerNavigationController:peoplePicker:shouldContinueAfterSelectingPerson: I'm doing:
MyVC *myVC = [[MyVc alloc] initWithNibName:#"XIBFileName" bundle:nil];
[self presentModalViewController:myVC animated:YES];
In my View Controller initWithNibName gets called, but not viewDidLoad. What am I doing wrong here?
Just try [peoplePickerVC presentModalViewController:myVC] instead of presenting from self.
The issue is that the peoplepickerviewcontroller will be in the top of the navigation stack. Becuase you wud've presented the peoplepicker from self. As this is the case, you wont be able to present/push from self as its not at the top of the navigation stack.
Otherwise once the peoplepicker has been poped, then you can further present from self.
I have relatively complex ui appearing in a popover (complex enough that doing all the layout and relationships from code would be a pain), but the button that calls it is created and placed into the parent view (which exists in the storyboard) from code.
I've tried making a popover segue from the parent view's viewcontroller object to the popover content vc, then triggering this with performSegueWithIdentifier. This almost works, but I can't figure out how to set the popOver's Anchor from code so it appears at the wrong place (squished at the bottom of the screen).
Is there a way to set the popOver segue's Anchor dynamically?
or
Can i create a UIPopOverController object and get the view i've put together in the storyboard into it?
or
Is there some other obvious way to do this that I'm not seeing?
please be gentle, I'm new here.
iPad iOS5.1 XCode4.3.2
Alex,
I'm not completely sure I understand what you're trying to do, but let me take a stab at it from what I think I understand.
For the same reason you cite (view complexity, etc.), I often build out my views in the storyboard and then load them from some action. What you can do is instantiate the view controller by identifier with something like this:
FancyViewController *controller = [[self storyboard]
instantiateViewControllerWithIdentifier:#"FancyViewController"];
This assumes you have created a UIViewController subclass called FancyViewController and have set the type for your view controller in the storyboard.
Now, you can display the view controller in a popover controller or you can push it onto a navigation stack. You just need to make sure you've set the identifier for your view controller in the storyboard.
Also, you'll probably want to instantiate your view controller once if you use a popover controller and just update the view controllers properties each time the action gets triggered. So, if it's tapping a button that triggers the popover, your code might look like this:
- (IBAction)didTapButtonToShowFancyViewController:(id)sender
{
if (![self fancyViewController])
{
// fancyViewContrller is a property of type FancyViewController *
fancyViewController = [[[self storyboard]
instantiateViewControllerWithIdentifier:#"FancyViewController"];
// fancyViewPopoverController is also a property
fancyViewPopoverController = [[UIPopoverController alloc]
initWithContentViewController:fancyViewController];
}
// Perform setup on the fancy controller you want to do every
// time the action gets triggered here. Do initialization in the if
// block above.
// Now display the popover from the sender's frame. I'm assuming the
// sender is a UIButton.
[fancyViewPopoverController presentPopoverFromRect:[sender valueForKey:#"frame"]
inView:[self view]
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
The only way to set the popover's "anchor" dynamically is to use an explicit action that calls presentPopoverFromRect:permittedArrowDirections:animated: instead of a segue.
I hope that helps. Let me know if I've misunderstood what you're trying to do.
Best regards.
I have a table view cell with a button that, when pressed, needs to call the method of a different view controller. I''ve followed this tutorial, which shows one way to get at another view controller in story boards, but it involves hardcoding the position of the view controllers. Anytime I'd change the order of my view controllers, I'd need to update my code, which I know I will mess up.
Here is their method:
UITabBarController *tabBarController = (UITabBarController *)
self.window.rootViewController;
UINavigationController *navigationController =
[[tabBarController viewControllers] objectAtIndex:0];
PlayersViewController *playersViewController =
[[navigationController viewControllers] objectAtIndex:0];
playersViewController.players = players;
Yikes, what is that?! We want to assign the players array to the
players property of PlayersViewController so it can use this array for
its data source. But the app delegate doesn’t know anything about
PlayersViewController yet, so it will have to dig through the
storyboard to find it. This is one of the limitations of storyboards
that I find annoying. With Interface Builder you always had a
reference to the App Delegate in your MainWindow.xib and you could
make connections from your top-level view controllers to outlets on
the App Delegate. That is currently not possible with storyboards. You
cannot make references to the app delegate from your top-level view
controllers. That’s unfortunate, but we can always get those
references programmatically.
Does anybody know a cleaner way?
I tried creating an IBOutlet in my table view cell to the other view controller, but I can't ctrl-click and drag to the other view controller for some reason.
I also tried setting the IBAction of my button in my other view controller, but I need to know what row was clicked, and the only information i can get from -(IBAction) addButtonClicked:(id)seder is the sender information, which is just RectButton.
Thanks!
As a workaround, you could set the tag property of the sender in InterfaceBuilder to something, and then just compare [sender tag] in the addButtonClicked: method. I believe tags are ints.