Create and Perform Segue Without Storyboards

Create and perform segue without storyboards

Segue it is component of the storyboard interaction it is possible to understand from name of the class UIStoryboardSegue. It is bad idea to create segues programmatically. If i am not making mistake storyboard creates them for you.

For solving of you're issue try to use some common ways like simply present ViewController.

let vc = self.storyboard?.instantiateViewControllerWithIdentifier("id") as! MyController
self.presentViewController(vc, animated: true, completion: nil)

As i understand from our conversation in comments. You would like to create navigation for tableview to details view using segues without storyboard. For now it is impossible to do this without storyboard.

For future learning try to investigate this information.

Segue without StoryBoard

You have to instantiate a viewController from storyboard, this way:

@IBAction func btnGoInicio(_ sender: Any) {

let storyboard = UIStoryboard(name: "Main", bundle: nil) // If you have other storyboard instead of Main, use it

if let page=self.storyboard?.instantiateViewControllerWithIdentifier("YOU_IDENTIFIER") as! MainVC{
//You MUST SET THE VIEW CONTROLLER IDENTIFIER "YOU_IDENTIFIER" FROM INSPECTOR INTO STORYBOARD
self.present(page, animated: true, completion: nil)
}

}

Possible to perform segue without the use of StoryBoard?

Interface Builder (IB) is just a GUI for programmatic development. Anything you can do in IB you can definitely do programmatically but not everything you can do programmatically you can do in IB, because IB is just for interface building—and just some interface building, not all.

segue is just IB terminology. In iOS, you can only display a view controller three ways: push (via UINavigationController), present (via a presentation object vendor UIViewControllerTransitioningDelegate), or show (a more generic approach to displaying a view controller).

Since you're new to programmatic iOS development (the best kind, IMO), a quick 101:

class ProgrammaticViewController: UIViewController {

override func loadView() {

// do not call super.loadView()
// most IB developers don't even know this method exists
// because this is where IB does its work
// add all of your view objects here (scroll views,
// table views, buttons, everything)

setView()
addTableView()
...

}

override func viewDidLoad() {
super.viewDidLoad()

// do call super.viewDidLoad(), however
// do your post-view setup here, like adding observers
// or fetching data
// this method is called after the entire view
// has been loaded into memory so consider that

}

// other lifecycle events that come after viewDidLoad where you
// can perform last-second work include viewDidLayoutSubviews(),
// viewWillAppear(), viewDidAppear(), etc.

deinit {
// do any cleanup here like deactivating timers, removing
// observers, etc.
}

// MARK: Methods

func setView() {

// if you're creating your view controller programmatically,
// you must create the view controller's actual view property
// and it must be done before adding any subviews to the
// view controller's view

view = UIView()
view.frame = UIScreen.main.bounds
view.backgroundColor = UIColor.white

}

}

If you are using auto layout (and you probably should be), you don't always need to explicitly set the frame of the view with view.frame = UIScreen.main.bounds. If it's the root view controller of the app, it's not needed—the window owns that view controller and it will set the frame. If you've then put a UINavigationController in the root and you're using auto layout, none of the view controllers you push to ever need their frame set as well. Therefore, the only real time you need to explicitly set the view's frame using something like view.frame = UIScreen.main.bounds is when you present a view controller modally. This is because a modally-presented view controller is not owned by the window or a navigation controller; it exists temporarily inside a transient container view. In this case, you must set its frame.

Passing data forward programmatically is simpler than it is for IB developers. Just instantiate a view controller, inject one of its (non-private) properties with a value, and push, present, or show it. Here's what a UITableView delegate for didSelectRowAt may look like:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

let p = indexPath.row
let detailViewController = SomeDetailViewController()

detailViewController.someProperty = searchResults[p]
navigationController?.pushViewController(detailViewController, animated: true)

}

And this is obviously doable because you've created that property in that view controller and not given it a private access modifier.

class SomeDetailViewController: UIViewController {

var dataObject: SomeType? // injectable
private var notInjectable: SomeType?

}

UPDATE: IB is clearly not the future of iOS development as far as Apple is concerned, with the introduction of SwiftUI, which is another way of programmatically developing iOS. Personally, I hate GUI programming and I'm happy to see it slowly phase out.

Creating a segue programmatically without a storyboard

I assume you meant a ViewController by the word page. So initialize your ViewController inside your func regSegue(){...} and present it using present(_:animated:completion:) method.

Example:

func regSegue(){
let page = PageViewController()
present(page, animated: true, completion: nil)
}

Unwind without Storyboard

You are not alone and you are not the first person to have this problem. I call this the problem of reverse routing.

To illustrate the problem, I'll show a storyboard version of a relatively complex unwind situation:

Sample Image

We have a tab bar controller with two children. The first child is a navigation controller which has pushed one view controller (the green v.c. at the end of the first row) on top of its root view controller (the yellow v.c.). The second child is a normal view controller that has presented one view controller (the white v.c. at the end of the second row).

The goal is to unwind from the white v.c. to the yellow v.c. in the top row.

If you're using a storyboard, this is trivial. The yellow v.c. contains an unwind method (the name isn't actually important), and you "hook" the exit segue from the button in the white v.c. to that method. At runtime, the user taps the button, and the runtime "magically" dismisses the white v.c., switches the tab bar controller to the first child, and pops the green v.c., leaving us in the yellow v.c. as desired.

Now do that in code! Uh, yeah, sure. How? That's the problem.

The irony is palpable. Clearly the runtime knows how to solve this problem, because it does solve the problem when you use an unwind segue in the storyboard. But there is no built-in programmatic analog when you are not using a storyboard. There is no unwind command that causes the complex unwind mechanism to become activated and do the same thing that would happen if this were a storyboard-based app.

This is a huge flaw in UIKit. Apple basically requires us to use storyboards. But everyone knows that any app developed by a team is likely to avoid storyboards, because reconciling versions of a storyboard through git is darned near impossible. So Apple doesn't seem to live in the real world; they have not provided the runtime support needed for real world development of apps.

A simple solution — simple to the point of crudeness — is just to unwind "by hand". The app has a "coordinator" object whose job is to take care of this sort of backward routing. If you are in the white v.c. and you want to "unwind" to the yellow v.c., your coordinator simply has to know that this is something we might want to do, and it knows what the necessary steps are in order to get there.

Basically, what I'm saying is that the coordinator must be supplied with a fixed list of all the backward routes the app will ever need to perform, along with instructions for how to perform them. Given where we are and where we want to go back to, the coordinator just performs the corresponding steps.

(You, the OP, will observe that I have not told you anything you don't already know. What I have outlined is, apparently, exactly your option 1. And that is correct. What I'm telling you is: option 2 would be nice, but it doesn't exist and isn't worth trying to write, so just fall back on option 1.)

prepare for segue programmatically with error: no segue with identifier ' value ''

Since you're not using the storyboard, you must push/present the YViewController instance programatically like so,

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let yInfo = YViewController()
yInfo.row = "hello"
self.present(yInfo, animated: true, completion: nil)
}

In the above code, yInfo is being presented. In case you want to push yInfo in navigation stack use pushViewController(_:animated:),

self.navigationController?.pushViewController(yInfo, animated: true)


Related Topics



Leave a reply



Submit