I am trying to make a splash screen. I have a view that has a background image being drawn onto it and then another view I want to transition to after a few seconds. I am trying to use the following code:
self.performSegueWithIdentifier("showApp", sender: self)
I created a segue between the two views by ctrl+dragging a line from one to the other. I set the segue's identifier to "showApp".
When I run the code nothing happens and there are no errors. Any ideas?
Here is the controller for the splash screen:
class SplashViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
sleep(2)
// THIS DOES NOTHING:
self.performSegueWithIdentifier("showApp", sender: self)
// THIS AS SUGGESTED ALSO DOES NOTHING:
var otherViewController:UIViewController = self.storyboard.instantiateViewControllerWithIdentifier("test") as UIViewController
self.presentViewController(otherViewController, animated: true, completion: nil)
}
}
Normally, you need a navigation controller in order to use segue.
Highlight your SplashViewController object inside the Storyboard and go to
Editor -> Embeded In -> Navigation Controller
After that, remove the code suggested by Clement and try running the project again, you should get the result that you expected.
Related
I'm creating an application where I place a view controller ontop of another with
Presentation: current context
But when I'm trying to dismiss the screen by dragging the top towards the bottom the view does not disappear.
I've also tried to add a button to make it dismiss but that doesn't work either.
#IBAction func dis(_ sender: Any) {
navigationController?.popViewController(animated: true)
self.dismiss(animated: true)
}
So, how can I dismiss both views when dragging the top one down when it uses "current context" as presentation style?
I'm using "current context" because the previous screen should never be displayed again. And instead of dragging down both, I would like to drag down just one to make both of them disappear. But it does not seem to work as expected.
Although "current context" is not for this purpose as #matt mentioned,
You should dismiss the controller who presents this one to dismiss both together in this case:
self.presentingViewController!.dismiss(animated: true) // `!` is to makeing sure it's not crashing.
Demo:
Use this simple code to demo:
class ViewController: UIViewController {
#IBAction func present() {
let destination = storyboard!.instantiateInitialViewController()!
if presentingViewController != nil {
// You are not in the A
if presentingViewController?.presentingViewController != nil {
// You are in the C
presentingViewController?.presentingViewController?.dismiss(animated: true)
return
} else {
// You are in the B
destination.modalPresentationStyle = .currentContext
}
}
present(destination, animated: true, completion: nil)
}
}
Usage:
Create a single view application
Drag a button into the view controller
Replace the ViewController class with the provided code
Connect the #IBAction
Run it to see the result.
If you use fullscreen presentation (so that there is no drag-to-dismiss) it's quite simple to do this with essentially no code at all.
Note that the yellow view controller appears as an intermediary when presenting, but not when dismissing.
I have a Tab bar in the first view and a total of two views.
However, when I move from the first view to the second view and then back to the first view using the Segue, the Tab bar of the first view disappears.
When return to the first view from the second view, what is the way the Tab bar does not disappear?(without using unwind)
Don't use unwind segue here. When you need to get back to previous ViewController, just dismiss your current ViewController
dismiss(animated: true, completion: nil) /* call this in second VC */
I suggest you read the documentation for understanding how combined View Controller Interfaces. Anyway, if you need to pop to previous view controller on the flow, you need to use
navController.popViewController(animated: true)
But, if the need to pop up on the specific ViewController on the queue of View Controllers in the NavigationViewController, you need to use
navController.popToViewController(ViewController, animated: true)
From the moment you are using a NavigationController, a return button will automatically appear on the UINavigationBar, so you do not have to worry about that. Unless you want to customize the back buttons in the viewcontrollers queue, in this case use the above methods.
It's for page 1. Display tabBarController once page is loaded.
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.tabBar.hidden = true
}
If click event is fired, hide tabBarController.
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "twoSegue") {
self.tabBarController?.tabBar.hidden = false
}
}
In my App I am using 5 ViewControllers. While I try to navigate to last one , It won't display. No error message displayed.
To go to next screen We are giving action to left swipe gesture using segue.
We have tried the solution provided in below link. They said to use push deprecated and then compile. Again use show segue(not specified Show / Show Details) we tried using both and the compile. It will solve the problem as it is issue with Xcode. But this solution doesn't work. I also not able to comment on their post.
Can UINavigationController only handle a maximum of 4 Viewcontrollers?
We have tried all navigation using segue Show, Show Details,Present Modally and
Push Deprecated.
In all segue except Push Deprecated controller neither go to fifth controller neither it give error. Push deprecated gives sigbart error while tried to run on iPhone.
We are using Xcode10 and iOS 12.0.
While developing same app in Xcode 9 Objective C code we have first 2 navigation are present modally, next two are having show segue and last one is present modally. It works fine on that code. We tried this solution also but it wont work. Currently I am upgrading same code in Swift with latest library and i am facing this issue. Please help.
There is no limit in number of pushed view controllers. Maybe it would be easier to add gesture recognizer in code on viewDidLoad for instance and put some breakpoints to see what goes on there.
To play around with these things you can try this minimalistic code which will push a new view controller on every tap. You can create a new project and simply overwrite the content of autogenerated ViewController and all should work:
import UIKit
class ViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
present(UINavigationController(rootViewController: MyViewController()), animated: true, completion: nil)
}
}
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onTap)))
self.title = "View controller \(navigationController?.viewControllers.count ?? 0)"
}
#objc private func onTap() {
navigationController?.pushViewController(MyViewController(), animated: true)
}
}
To explain:
An instance of ViewController will be created as a root view controller in your main window which is part of project settings (which storyboard to use) and part of autogenerated storyboard named main.
We need to wait for view to appear of the first view controller before we can present our new navigation view controller. We presented with having a root view controller as our own subclass of view controller called MyViewController. This view controller is not in storyboard.
When an instance of MyViewController comes into hierarchy (using push or present) a viewDidLoad will be called which creates a tap gesture recognizer set to a method to push a new instance of MyViewController. We also set a title depending on the number of view controllers on navigation controller just to have more information.
As said this is a minimalistic code. But in general you would do something like:
override func viewDidLoad() {
super.viewDidLoad()
view.addGestureRecognizer({
let swipeRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(onSwipeLeft))
swipeRecognizer.direction = .left
return swipeRecognizer
}())
}
#objc private func onSwipeLeft() {
let controllerToBePushed = UIStoryboard(name: "my_storyboard_name", bundle: nil).instantiateViewController(withIdentifier: "the_identifier_I_set_in_storyboard") as! WhateverTheTypeOfMyViewControllerIs
navigationController?.pushViewController(controllerToBePushed, animated: true)
}
I am working in storyboard and also programmatically do some things. First, I have created a viewController controller which is login page (first view) programmatically. But in storyboard I have a NavigationController whose root is ViewController. Everything (methods forgotPassword and loginDidFinish) worked fine, except that ViewController was viewed before controller immediately after launching the app.
So I have changed the root of NavigationController to controller, and after that my functions does not work. I've tried several things like deleting navcontrol in storyboard, etc. You can see my project here: https://github.com/ardulat/SPE
I will provide you a basic example of a Login scenario, hope it can help you with your issue, what I would do first is set right the navigation between ViewControllers like this:
I have two view controllers in my project (LoginViewController.swift and MainViewController.swift):
So in my storyboard I create two ViewControllers, the first one embedded with NavigationController then I set a segue from my first ViewController to my second ViewController:
Then I give a name to the segue I created like so:
And in order to navigate from Login to Main ViewController, I call the performSegue method inside the loginButtonTapped action that is triggered when the login button is touched.
LoginViewController.swift:
class LoginViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func loginButtonTapped(_ sender: AnyObject) {
// TODO: validate your login form
performSegue(withIdentifier: "LoginToMain", sender: nil)
}
}
I want to Show (e.g. push) segues in my storyboard, to connect my viewcontrollers and my navigation controller. Then the navigation bars on the viewcontrollers will show correctly.
For example: With show detail or present modaly, the navigation bar will disappear
But I don't want segue animation.
Xcode is giving the warning like : "Disabling segue animation is not available prior to iOS 9.0"
And I wants deployment target of iOS 7.0 or 8.0
How can I solve this?
Thanks in advance.
You can disable animations before performing the segue and after enable it again.
UIView.setAnimationsEnabled(false)
self.performSegueWithIdentifier("next", sender: nil)
UIView.setAnimationsEnabled(true)
This will perform the segue without the animation.
Click on segue arrow in Main.Storyboard and then:
Check out Animates
If you want to switch animate state in the code, You can duplicate your segue in the storyboard, with different identifiers, and the same origin and destination. Then make one of theme animates and the other not. Then, do performSegue with the desired identifier.
class MyNavigationController : UINavigationController {
var firstTransitionAnimated : Bool = true // or false, based on initialization
override func viewDidLoad() {
super.viewDidLoad()
var properSegue = firstTransitionAnimated ? "animated_segue" : "not_animated_segue"
self.performSegue(withIdentifier: properSegue, sender: self)
}
}
I made a custom segue, using the Swift answer in this thread:
Push segue in xcode with no animation
So:
class ShowNoAnimationSegue: UIStoryboardSegue {
override func perform() {
let source = sourceViewController as UIViewController
if let navigation = source.navigationController {
navigation.pushViewController(destinationViewController as UIViewController, animated: false)
}
}
}
And in Xcode, in the Attributes Inspector of the custom Segues, I have checked the 'Animates' box (YES). Now the warning is gone, so that is why I am answering my own question.
I am not really sure yet if it is a durable solution.