I have UIPageViewController with 3 UIViewControllers ("FirstVC", "SecondVC", "ThirdVC").
ViewControllers changes by scroll, but I need to change its by click on UIButtons.
How I can do this?
Maybe some func, in which VC will setup by StoryboardID?
Thanks for all answers!
You can easily programmatically navigate through the pages of a UIPageViewController using:
setViewControllers([targetPage], direction: .forward, animated: true, completion: nil)
In the case where you have a UIPageViewController embedded in a ContainerView, and you want buttons in the "root" view to control the page view controller, the basic process is:
add navigation methods (funcs) to your page view controller class
save a reference to the page view controller when it is loaded have
your buttons call the navigation funcs using that reference
When your "root" view controllers loads and instantiates the view controller that is embedded in your ContainerView, it calls prepare(for segue:...) - which is where you get your reference.
In Storyboard, where you embed your view controller in the ContainerView, you will see a standard "segue" connection. In the Attributes Inspector, give that segue an Identifier, such as "PageControllerEmbedSegue".
In your root controller class, add a class-level var:
var myPageVC: BasicPageViewController?
and in prepare():
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// get a reference to the embedded PageViewController on load
if let vc = segue.destination as? BasicPageViewController,
segue.identifier == "PageControllerEmbedSegue" {
self.myPageVC = vc
}
}
Now, you can call functions / get properties of your embedded view controller.
I have a full example on GitHub: https://github.com/DonMag/EmbeddedPageView
There are a couple ways. You could add a segue in the Storyboard file and call
performSegue(withIdentifier: "toResponseTime", sender: self)
otherwise you could do something like.
let controller = self.storyboard!.instantiateViewController(withIdentifier: "AngelDetailViewController") as! AngelDetailViewController
self.navigationController!.pushViewController(controller, animated: true)
Related
I have a popover view which is simply a stack of UIButtons.
The popover is presented from a view controller (Records) which is itself inside a NavigationController.
I need the buttons in popover view to be able to push other views on top of the navigation stack.
Here's how I prepare the segue for the popover in the Records view controller:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "popoverSegue" {
let dest = segue.destination as! PopoverViewController
dest.navController = navigationController
dest.modalPresentationStyle = .popover
dest.popoverPresentationController?.barButtonItem = addButton
dest.popoverPresentationController?.delegate = self
}
}
Then inside the popoverViewController I got a bunch of IBAction functions where I need to push other views on top of the navController that was set above.
let editor = EditorViewController(nibName: "EditorViewController", bundle: nil)
navController?.pushViewController(editor, animated: true)
This kina works and the editor view shows up with a nav bar and all, but as soon as I tap on the view or try to scroll, it just gets dismissed.
How can I prevent that dismiss thing? I did try setting isModalInPresentation. It didn't work for me.
Answering, as per OP's comments...
The proper approach is to have your "popover" controller tell the presenting controller to push a new VC onto the navigation stack.
This can be done in a few different ways, but most commonly by using either the protocol/delegate pattern or with closures.
i am a beginner in iOS development, and recently, i just follow along the tutorial for beginners.
let say i want to move from one VC to another VC by clicking a button, so i just find out that there are three ways to move from one ViewController to another ViewController (modal segue).
in main storyboard, i just click control and drag from the button to th destination view controller and choose present modally
programmaticaly, by implementing the code below
#IBAction func logInButtonDidPressed(_ sender: Any) {
// modal transition to VC2
let viewController2 =
storyboard?.instantiateViewController(withIdentifier:
"ViewController2") as! ViewController2
present(viewController2, animated: true, completion: nil)
}
programatically,by using perform segue function
#IBAction func logInButtonDidPressed(_ sender: Any) {
performSegue(withIdentifier: "toSecondViewController", sender: self)
}
are they just the same ? or is it used for different cases?
Thanks in advance :)
Yes, they are similar. And the obvious difference I think is the data passing. The first and third one are same, use the following method to pass data to next controller:
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if let viewController2 = segue.destination as? ViewController2 {
viewController2.someProperty = someValue
}
}
For second transition, you directly set the data when creating the next controller:
let viewController2 = storyboard?.instantiateViewController(withIdentifier:
"ViewController2") as! ViewController2
viewController2.someProperty = someValue
present(viewController2, animated: true, completion: nil)
I would use segues, as there are some advantages compared to manual presentation:
You can create unwind segues to exit the current view controller to any view controller in the hierarchy.
You can add 3D touch support to segues with one mouse click.
The first and last method produce identical results. I would create segues with clicking and dragging whenever possible. If you need to do some data validation or other stuff before performing a transition, you have to call the performSegue method manually.
How would I go about dismissing a view controller once a segue has been performed? Once the new view controller has animated on top, I want to dismiss the view controller underneath (the one which the segue was initially triggered from).
I tried the following code but I am getting issues with views not being in the heirarchy.
#IBAction func gotoSection1(_ sender: AnyObject) {
let presentingViewController: UIViewController! = self.presentingViewController
self.dismiss(animated: false) {
presentingViewController.dismiss(animated: false, completion: nil)
}
}
Any help would be greatly apprceiated.
Try this:
Add the below code to first view controller.
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
self.dismiss(animated: true, completion: nil)
}
It will dismiss the first view controller before presenting second view controller on top of it.
Edit:
Follow these steps and check:
Create a button in 1st View controller
Connect button to 2nd View controller with modal segue
Implement prepareForSegue in 1st view controller
Refer to these links:
Navigation Controller
https://developer.apple.com/reference/uikit/uinavigationcontroller
Presenting a controller
https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/PresentingaViewController.html#//apple_ref/doc/uid/TP40007457-CH14-SW1
I have a storyboard with two main view controllers (ViewController / SecondViewController) and a container with an embedSegue that displays the EmbeddedViewController view.
Desired Result
I would like to pass the 5 from ViewController to EmbeddedViewController using prepareForSegue (I don't see a need for delegation here, since the data is only going 1 way, and that's TO the EmbeddedViewController.) Once "Segue" button is pressed, the second view controller appears with the yellow VC embedded with 5 in it.
Note - SecondViewController has no user interaction in displaying EmbeddedViewController. It just shows up automatically.
Problem
I can't get a reference to EmbeddedViewController from the mainSegue prepareForSegue. Nor can I access any child View Controllers from SecondViewController. Thought I could access properties of EmbeddedViewController if I access the children VC's of SecondViewController. See code below.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "mainSegue" {
let secondVCSegue = segue.destinationViewController as! SecondViewController
print("array -- \(secondVCSegue.childViewControllers)")
// Array prints nothing. Just a blank [] :(
}
}
Any tips are appreciated thanks.
I have a sent Action, as follows:
#IBAction func showSettings(sender: AnyObject) {
let settingsPicker = SettingsViewController()
settingsPicker.setDelegate(self)
let navigationController = UINavigationController (rootViewController: settingsPicker)
self.presentViewController(navigationController, animated: true, completion: nil)
}
The method creates a controller, sets a reference to the delegate, and creates a navigation controller.
All this works, however the widgets defined in the story board do not appear. The SettingsViewController should manage a ui which is defined in a story board. I presume becuase I create it programmatically none of the widgets appear. The SettingsViewController does not programmatically create widgets, the are declaratively defined in the story board.
If I link (in the storyboard) the two controllers with a segue, then the widgets appear, but my action is not being used.
How can I use my action and present the view controller / ui as defined in the storyboard?
When you create a segue between your UIViewControllers, you should define an identifier, eg: "settingsSegue".
In your code you can then perform that segue by calling the segue with the identifier:
#IBAction func showSetting(sender: AnyObject) {
performSegueWithIdentifier("settingsSegue", sender: nil)
}
To set up the SettingsViewController you should implement the following:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){
if let settingsController = segue.destinationViewController as? SettingsViewController {
settingsController.delegate = self
}
}
Interacting with Storyboard and Segues
If you want to invoke a segue through code, see Laffen's answer.
If you want to create a view controller that's defined in your storyboard and then display it programmatically, use instantiateViewControllerWithIdentifier to create a new instance of your view controller, then display it to the screen as desired (present it modally, push it onto your navigation stack, or whatever you want to do.)