I am trying to do a segue to another screen using code but it shows me a black screen using Xcode 7 beta 6.
here is my 1st view controller file code
// ViewController.swift
// Segue through programming
//
import UIKit
class ViewController: UIViewController{
#IBAction func buttonPressed(sender: AnyObject) {
presentViewController(secondController(), animated: true) { () -> Void in
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
This will only work if secondController programmatically creates its view. If you want to use a storyboard scene (which is far more common), you can do the following:
#IBAction func buttonPressed(sender: AnyObject) {
let controller = storyboard?.instantiateViewControllerWithIdentifier("foo")
presentViewController(controller!, animated: true, completion: nil)
}
That obviously assumes that you've specified a storyboard identifier for the destination scene.
Or, you can created a segue between the two scenes in IB by control dragging from the view controller icon at the top of the first scene to the second scene:
and then give that segue its own storyboard id:
Then you can invoke the segue programmatically:
#IBAction func buttonPressed(sender: AnyObject) {
performSegueWithIdentifier("bar", sender: self)
}
Related
In my application I used SWRevealViewController in order to implement the side menu. There, for some reason I had to put a view which is embed in a navigation controller, before the reveal view controller.
This is my storyboard
Everything works fine other than one thing. when I drag from the left edge of the screen to the right side (pan gesture) on my home view, instead of side menu it navigates me to the previous view (in here case to the middle view which contains a button in the middle).
This is how it looks like when dragging
I want to avoid this and get the side menu when dragging like that. Can someone help me on this. Any help would be highly appreciated.
Edit:
This is the front_view and rear_view
Take a ViewController.swift file for the initial ViewController having button.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// 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.
}
*/
}
There is no issue in the swrevealviewcontroller implementation but the native behavior of navigation controller is causing this issue.
You need to remove the popGesture from the navigation controller in any view controllers that you don't want to be able to use the swipe gesture:
var gestureRecognizer: UIGestureRecognizer? {
guard let nc = navigationController else { return nil }
return nc.interactivePopGestureRecognizer
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if let gr = gestureRecognizer {
gr.isEnabled = false
}
}
Here is my problem.
I have ViewController A (let's call it only A).
I push from A to B, which is custom camera controller.
When I take picture, I present modally controller C which has two buttons, one for confirm and one for going back.
If back button is tapped, it goes back to B controller.
If confirm button is tapped, C should trigger delegate method to A, and then dismiss C and B, but without animation so dismissing B won't be noticed.
Questions:
1. How to achieve the above described scenario? A needs to be delegate to C, so how to do that? Also should I use unwinding?
Reminder: A -> push -> B -> modal -> C
I think you can do same functionality with just pass reference of B to C controller
Controller B Code
class BViewController: UIViewController {
weak var controllerA : ViewController!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func confirmEventCallFromC() {
self.navigationController?.popViewController(animated: false)
}
#IBAction func btnClick(_ sender: Any) {
self.performSegue(withIdentifier: "CVC", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "CVC" {
let vc = segue.destination as! CViewController
vc.controllerB = self
}
}
}
And Controller C Code is like this
class CViewController: UIViewController {
weak var controllerB : BViewController!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func confirmBtnClick(_ sender: Any) {
controllerB.confirmEventCallFromC()
self.dismiss(animated: true, completion: nil)
}
}
i hope this will help you.
You can make use of UnwindSegue,
You can declare a method in VC A as
#IBAction func unWindToVCA(segue : UIStoryboardSegue) {
}
In VC C storyboard , you can control drag from viewController to exit and you will prompted with a popover which will have a list of all the unwind segues you have declared before. Select the unWindToVCA.
Now select the segue and assign a reusable identifier to it as shown in pic below :)
Finally whenever you want to go back to VC1, call
self.performSegue(withIdentifier: "backToVC1", sender: nil)
Now in VCA you can get the data from VC C using,
#IBAction func unWindToVCA(segue : UIStoryboardSegue) {
let c = segue.source
//access c's data and update A
}
I have followed your hierarchy of VC's as well
VC A -> push VC B -> modal -> VC C
I have a TabBarController with 5 ViewControllers within it, on one of the ViewControllers, I have a set of buttons which load different view controllers outside of the TabBarController. These are loaded though the Modal Segue's, however the issue I am having is when I try to go back to the View within the Tab Bar it loads but without the Tab Bar itself, the code I have is:
class GreetingsVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func goBack(sender: AnyObject) {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewControllerWithIdentifier("anonScreen") as! AnonVC
self.presentViewController(nextViewController, animated:true, completion:nil)
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
How can I make it so when the back button is pressed it presents the View Controller from the Tab Bar Controller?
From my understanding, from the tabbar controller, you have present the GreetingsVC using presentViewController and you want to go back to previous view (one of the tabbar view controllers)
Instead of using presentViewController, you need to use dismissViewControllerAnimated
#IBAction func goBack(sender: AnyObject) {
dismissViewControllerAnimated(true, completion: nil)
}
I've setup a walkthrough view at the beginning of my app using BWWalkthrough and it works fine. Now I'm just trying to skip that view if the user has already seen it. Pretty simple right? But somehow it is not working. This is what I have:
On my storyboard I setup a segue between the BWWalkthroughViewController and the main view of my app and called it "RootView"
And this is my code:
class TutorialViewController: BWWalkthroughViewController {
#IBOutlet weak var endTutorialButton: UIButton!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// Check if should skip this viewcontroller
let shouldSkipTutorial = NSUserDefaults().boolForKey(Constants.UserPreferences.TUTORIAL_SEEN_KEY)
if shouldSkipTutorial {
// In debugger this part is reached but the segue is not executed
finishTutorial()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Here I setup everything walkthrough related
}
// This is called when the user reaches the end of the walkthrough and press the finish button. The weird part is, this works fine! walkthrough is dismissed and next ViewController is pushed.
#IBAction func endTutorial(sender: AnyObject) {
NSUserDefaults().setBool(true, forKey: Constants.UserPreferences.TUTORIAL_SEEN_KEY)
finishTutorial()
}
func finishTutorial() {
self.performSegueWithIdentifier("ShowRoot", sender: nil)
}
}
Where can the problem be?
I have a split view controller. Everything loads properly, except when you're in portrait and you rotate to landscape, the cell current gets de-selected.
I found the problem. The table was reloading data every time the viewWillAppear function was called, and viewWillAppear is called every time the device is rotated.
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
table.reloadData()
}
Now there's a new issue. I need to update the TableView whenever I add an item from a modal view.
The modal view is another view controller. I tried:
MasterViewContoller().table.reloadData()
That raised a bunch of flags and I'm pretty sure that's not the right way to do it. So how can I reload the table from another view?
==============
For those think that the ViewWillAppear is not called on rotation, try this and see:
class MasterViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
println("rotated")
}
}
class DetailedViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
The standard solution to your problem is to use a delegate.
protocol ModalViewControllerDelegate {
func updateInModalViewController(sender: ModalViewController)
}
class MainViewController: UIViewController, ModalViewControllerDelegate {
func prepareForSegue(_ segue: UIStoryboardSegue, sender sender: AnyObject?) {
if let controller = segue.destinationViewController as? ModalViewController {
controller.delegate = self
}
}
// the rest should be pretty obvious
}