How to segue programmatically in iOS using Swift
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Programmatically triggering a segue in iOS is useful when navigation depends on validation, network results, permissions, or any other runtime condition. Storyboards still define the transition, but your code decides when to run it. In UIKit, the most direct way is performSegue(withIdentifier:sender:).
Creating the Segue in Interface Builder
Even for a programmatic segue, you usually create the segue visually in the storyboard first. Connect the source view controller to the destination view controller, then assign a segue identifier such as ShowDetails.
That identifier is what your Swift code will use later. Without it, performSegue has no way to know which transition to execute.
Triggering the Segue from Code
Here is a common UIKit example. A button tap checks whether the form is valid and only then triggers navigation.
This keeps navigation tied to actual business logic instead of wiring the transition directly to the button in the storyboard.
Passing Data in prepare(for:sender:)
Running the segue is only half of the pattern. Most of the time you also need to configure the destination controller before it appears.
prepare(for:sender:) is the right place to inject data into the destination when you are using storyboard segues. Keep it focused on configuration rather than complex logic.
Deciding Whether a Segue Should Happen
If a segue can also be triggered from the storyboard, you can intercept it with shouldPerformSegue(withIdentifier:sender:). This is useful when a button is wired to a segue visually, but navigation should be blocked under some conditions.
If you are already calling performSegue yourself, you often do not need this override because the guard logic can live in the action method.
Segue vs Direct Navigation
A common source of confusion is treating every navigation path as a segue. If you create view controllers entirely in code or use a navigation controller without storyboards, you may push or present the destination directly instead.
That is not a segue. It is direct navigation. Both approaches are valid, but they solve slightly different problems.
Common Pitfalls
The most frequent failure is a mismatched segue identifier. If the storyboard uses ShowDashboard and your code calls showDashboard, the app crashes at runtime because the identifier must match exactly.
Another common issue is forgetting that the destination may be wrapped in another container, such as a navigation controller. In those cases, segue.destination is the container, not the final content controller.
Developers also put too much logic into prepare(for:sender:). That method should configure the destination, not perform validation, networking, or side effects that belong earlier in the flow.
Finally, avoid mixing storyboard-triggered segues and manual performSegue calls for the same user action unless the control flow is very clear. Otherwise, you may trigger navigation twice or make debugging harder than necessary.
Summary
- Create the segue in the storyboard and assign a stable identifier.
- Call
performSegue(withIdentifier:sender:)when runtime logic should decide when navigation happens. - Pass data in
prepare(for:sender:)before the destination appears. - Use
shouldPerformSegueonly when storyboard wiring needs a final gate. - Prefer direct
pushViewControllerorpresentwhen the destination is created entirely in code.

