I have just made a small transition so my project loads a different storyboard as its main (did it in the info.plist).
I have my new storyboard to keep my viewController that are responsible for login screen etc. Just to make it more clear.
After the login button is tapped I want to initiate a navigationController from another storyboard:
func instantiateViewController(fromStoryboard storyboard: String, withIdentifier identifier: String) -> UIViewController! {
let storyboard = UIStoryboard(name: storyboard, bundle: nil)
let viewController = storyboard.instantiateViewControllerWithIdentifier(identifier)
return viewController
}
#IBAction func loginButtonTapped(sender: UIButton) {
let viewController = instantiateViewController(fromStoryboard: "Main", withIdentifier: "MainNavigationController")
presentViewController(viewController, animated: true, completion: nil)
}
Everything works correctly but one thing is driving me nuts.
After presenting the MainNavigationController from Main.storyboard its view hierarchy is not maintained.
What I mean is, the labels and buttons which supposed to be on top of another, full screen UIView (but are not its child and so they should remain) are now behind it.
What might be causing this and what is the simplest way to make them appear on top (as they do whey I open main.storyboard)
EDIT
I added a line of code in the rootView of the MainNavigationController in its viewDidLoad method:
self.view.sendSubviewToBack(wholeScreenView)
and it solved the problem.
However, does anybody know why do I have to code it myself and the views are not like in the Main.storyboard?
The storyboard is not configured the way you think it is. Your wholeScreenView is in fact in front of the other views, in the storyboard. The other views (the labels and buttons) are not subviews of wholeScreenView; they are subviews of the main view, and so is wholeScreenView. It is a later subview, so it is in front of them.
Related
I am learning iOS with few sample projects. I have two view controllers in that first VC has few buttons and a mapview and the second VC has tableview showing a set of results. I have embed the both viewcontrollers in navigationViewController.By clicking a button from First VC i am able to show the tableview (using show segue) and able to go back to first VC through navigation. Now my query is I want to display the tableview (second VC) in place of one view object (map view) defined in firstVC rather than padding the tableview entirely in full screen. My problem is when showing another Viewcontroller i still want to see the few viewobjects from firstVC so I am trying to display the secondVC on top of mapview when i click on a button which triggers the segue.I have to use the single interface, so I need to load the tablview results from SecondVC into firstVC by replacing mapView's view with tableview.Please let me know your ideas if it is possible and any other ideas to achieve the same are most welcomed.
Sreekanth Gundlapalli,
All you need to do is to add the TableView controller's view as subview to your view Controller. In order to simplify the process I personally prefer using the ContainerView,
Step 1 : Add a ContainerView to your View Controller and add the auto layout constraints to it, because your tableView will be loaded inside this container view you donate have to apply any auto layout constraint to your tableView to keep it in place :)
ex :
Step 2 : Drag an IBOutlet to the container view.lets call it as containerView :)
Step 3 : Now its up to you to have two view controller 1 for loading map and 1 for loading tableView, or you will have map view as your view controller subview and you will either hide it or remove it and add container view but I personally prefer having code clean n neat so I prefer having two different VCs
so lets create 2 VCs lets call them as viewController1 & viewController2 Savy ??
Step 4 :
lets write a method which actually loads VC and adds its view as subview to your ViewController
func changeEmbededVC(for status : Int) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if status == 0 {
mehereButton.tag = 1
let vc = storyboard.instantiateViewController(withIdentifier: "viewController1")
vc.willMove(toParentViewController: self)
containerView.addSubview(vc.view)
self.addChildViewController(vc)
vc.didMove(toParentViewController: self)
}
else {
mehereButton.tag = 0
let vc = storyboard.instantiateViewController(withIdentifier: "viewController2")
vc.willMove(toParentViewController: self)
containerView.addSubview(vc.view)
self.addChildViewController(vc)
vc.didMove(toParentViewController: self)
}
}
I believe code is pretty self explanatory :D now what is mehereButton.tag = 1 ?? Simple you want to toggle view on button press don't you :D hence I have created a IBOutlet for mehereButton and changing its tag :)
now finally in IBAction of mehereButton
#IBAction func buttonTapped(_ sender: UIButton) {
self.changeEmbededVC(for: self.mehereButton.tag)
}
but we need to load one of the view by default isn't it :D
so change your viewDidAppear to
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.changeEmbededVC(for: 0)
}
Hope I answered your question In detail :P I know you can't neither up vote or accept answer as you don't have enough reputation :) but hope it will help somebody in future as well :)
I am facing a problem I cannot solve alone. At least, I don't know what's the right way to program this. I am writing an app which will open a PopupView as a Subview of my main menu when pressing + . This looks like this:
As soon as this subview is visible, I want to perform different segues (when pressing button 1,2,3 or 4) so this popup can change the view to 1-4:
I created a separate Storyboard for this popup and when pressing +, the initial view of it will be added as a subview:
let addFilePopup : UIStoryboard = UIStoryboard(name: "AddFilePopup", bundle: nil)
animations.showInView(self.view, aView: addFilePopup.instantiateInitialViewController()?.view, animated: true)
// the method for adding the PopupView as a Subview
func showInView(superView: UIView, aView: UIView!, animated: Bool)
{
aView.center = superView.center
superView.addSubview(aView)
if animated
{
self.showAnimate(aView)
}
}
Showing the Popup itself works so far, but as soon as I press one button, the segue of the Popup is not performed... Do you have any hints to me for this problem? Besides, is this the right approach?
If you also could let me know how I can make the superview.alpha = 0,5 and ignoring touches without taking affect on the subview that would be great too. Thanks in advance!
How can I perform segue from one .xib (TableCell.xib) to another .xib(UIViewController) on click on TableCell?
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print(results?[indexPath.row]) // prints successfully
...
// apply below chunks here...
}
First, I tried setting up a manual segue in Storyboard. Note that, TableView & TableViewCell are external xib but parent of TableView is in Storyboard. So, I tried control-dragging from parent-ViewController to the detailViewController (and identifier: showDetails)..However, doesn't work.
...
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self.performSegueWithIdentifier("showDetails", sender: AnyObject?())
})
...
Obviously, I received this error (because TableView is in .xib whereas parent and detailsVC are in Storyboard and I ctrl+dragged from parentVC to detailsVC but TableView1 apparently doesn't recognise the segue in Main Storyboard):
TableView1: 0x7f97626a3280>) has no segue with identifier 'showDetails''
Then I tried creating a ViewController and tried adding var parentNavigationController : UINavigationController! at the top and referencing below chunk inside didSelectRowAtIndex
...
let newVC : UIViewController = CellDetailsVC()
newVC.title = "DetailsView"
print(newVC)
parentNavigationController!.pushViewController(newVC, animated: true)
However, I am receiving an error:
DetailsVC: 0x7ff7794ae550>
fatal error: unexpectedly found nil while unwrapping an Optional value
Finally, I also tried below chunk inside didSelectRowAtIndex, and got something close (as I can use dismissView to < Back); but not exactly what I want. Its problem is that the segue animation looks like the page is coming from bottom.
...
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("VideoDetailsVC") as UIViewController
self.presentViewController(vc, animated: true, completion: nil)
}
I am also receiving a warning (but not crash) for some reason I couldn't figure out:
Presenting view controllers on detached view controllers is discouraged
Which approach is the right one? Or is there a better way to adapt to achieve what I am trying to?
Firstly, what is the right way to perform segue from didSelectRowAtIndex (in TableView.xib class) to a new ViewController (either Storyboard or xib)?
Secondly, assume that there is an image thumbnail in the TableViewCell.xib. What is right way of performing segue to a new UIView on click on that view? (like full-screen image / dismiss-able)
Your second approach looks to be right one but of course you are doing something wrong there. You need to drag and drop Segue from Parent ViewController to Detail ViewController and give it a Segue identifier in Storyboard (check attached Image below). IN didSelectRowAtIndexPath you need to do below code:
self.performSegueWithIdentifier("showDetailViewController", sender: nil)
As I can see you already tried that but it looks like you missed some step either setting Segue Identifier or giving wrong identifier in performSegueWithIdentifier method. Also your Parent ViewController should be embedded in UINavigationController in case you are missing that thing :)
Also keep in mind you should perform navigation (here its Segue) from one ViewController to another ViewController at same level not from one View to another ViewController.
I am trying to open next viewController after choosing photo from gallery. I can get image from gallery, but after that I dont know how to open controller next to it. !.This is photo of that storyboard
You can put an UITapGestureRecognizer inside your UIImageView using Interface Builder or in code (as you want), I prefer the first. The you can put an #IBAction and handle the tap inside your UIImageView, Don't forget to set the UserInteractionEnabled to true in Interface Builder or in code.
To present the next view controller you can do it in code like below or just using Interface Builder using a segue through the UITapGestureRecognizer you set before (it's up to you).
To present the view controller manually like in the following code you need to set the Storyboard ID for you view controller like in the following picture (in the Identity Inspector panel):
#IBAction func imageTapped(sender: AnyObject) {
// Set the storyboard name by default is Main
let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
// Instantiate the ViewController with the name you set before like in the image
let nextViewController = storyboard.instantiateViewControllerWithIdentifier("ViewControllerB") as! UIViewController
// present the nextViewController
self.presentViewController(nextViewController, animated: true, completion: nil)
}
I hope this help you.
I was wondering if i could make some sort of a segue between these 2 views in a Xib file.
the main View is loaded into a scrollview in the storyboard.
.
(so if ik click Bewerken(edit) i would get pushed to the view controller on the right)
Thanks!
I would suggest changing this to a Container View inside the storyboard instead of a separated Xib. You can add and position/size UIContainerView as a subview and add a"Storyboard Embed Segue to attach another ViewController. This is what it will look like in IB/Storyboard:
During runtime, the blue UIView (or the embedded UIViewController if you like) will be embedded in the hosting UIView as a subview:
If you change your implementation to this, you are in the beautiful segue world where you can just drag-and-drop segues :)
You could do 2 things:
1 - Wrap the main view in a Navigation Controller so you can do the following:
#IBAction func loadEditController(sender:UIButton){
let editController = RegisterController(nibName:"RegisterXIB", bundle:nil)
navigationController?.pushViewController(editController, animated: true)
}
2 - Present the Edit Controller over the current context and animate it yourself
#IBAction func loadEditController(sender:UIButton){
let editController = RegisterController(nibName:"RegisterXIB", bundle:nil)
editController.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
presentViewController(editController, animated: false, completion: nil)
//Move it offscreen and the animate it here
}