Performseguewithidentifier in Swift

Swift performSegueWithIdentifier not working

[Assuming that your code is not crashing, but rather just failing to segue]

At least one problem is:

self.performSegueWithIdentifier("Test", sender: self)

should be:

dispatch_async(dispatch_get_main_queue()) {
[unowned self] in
self.performSegueWithIdentifier("Test", sender: self)
}

Remember that all UI operations must be performed on the main thread's queue. You can prove to yourself you're on the wrong thread by checking:

NSThread.isMainThread() // is going to be false in the PF completion handler

ADDENDUM

If there's any chance self might become nil, such as getting dismissed or otherwise deallocated because it's not needed, you should capture self weakly as [weak self] not unowned, and use safe unwrapping: if let s = self { s.doStuff() } or optional chaining: self?.doStuff(...)

ADDENDUM 2

This seems to be a popular answer so it's important to mention this newer alternative here:

NSOperationQueue.mainQueue().addOperationWithBlock {
[weak self] in
self?.performSegueWithIdentifier("Test", sender: self)
}

Note, from https://www.raywenderlich.com/76341/use-nsoperation-nsoperationqueue-swift:

NSOperation vs. Grand Central Dispatch (GCD)

GCD [dispatch_* calls] is a lightweight way to represent units of work that are going to be executed concurrently.

NSOperation adds a little extra overhead compared to GCD, but you can add dependency among various operations and re-use, cancel or suspend them.

ADDENDUM 3

Apple hides the single-threaded rule here:

NOTE

For the most part, use UIKit classes only from your app’s main thread.
This is particularly true for classes derived from UIResponder or that
involve manipulating your app’s user interface in any way.

SWIFT 4

DispatchQueue.main.async(){
self.performSegue(withIdentifier: "Test", sender: self)
}

Reference:

https://developer.apple.com/documentation/uikit

performSegueWithIdentifier not working if called from viewDidLoad

EXPLANATION:

Your View hasn't appeared yet when you call your checkStoredUser().

EASY FIX:

Put it in viewDidAppear() like this:

override func viewDidAppear(animated:Bool) {
super.viewDidAppear(false)
checkStoredUser()
}

swift performSegueWithIdentifier sender value

As @iosDev82 says in his answer, sender is an optional that names the object (if any) that triggered the segue.

If you trigger a segue through code in a view controller, you could pass the view controller (self), or you could pass nil. It's just a piece of information that is passed along to prepareForSegue (again as iOSDv82 says.)

If you trigger a segue in the code of an IBAction method, your IBAction may have it's own sender parameter (frequently a button.) In that case you can pass along the sender parameter to the performSegueWithIdentifier method.

Example:

@IBAction func buttonAction(sender: UIButton)
{
//In this case the button IBAction takes a pointer to the button as a param.
//Pass it on to the segue in case performWithSegue needs it.
self.performSegueWithIdentifier("someID", sender: sender)
}

prepareForSegue and PerformSegueWithIdentifier sender

There are, effectively, two ways you can trigger a segue. The first is via an action on a UI element in Interface Builder, the second is using performSegueWithIdentifier:sender: in your code. I say 'effectively', because under the covers, when the scene is loaded from the storyboard, an action handler is configured that ultimately calls performSegueWithIdentifier:sender:

When performSegueWithIdentifier:sender: is called, the segue object is delivered to your view controller's prepareForSegue:sender: function.

In the case where the segue was initiated by an action on a UI element then the sender will be that UI element (i.e. if it is an action connection on a UIButton then the sender will be the UIButton instance).

If the segue is initiated by your code calling performSegueWithIdentifier:sender: then the sender will be whatever object you passed as the sender. This could be your view controller, a button, an array, anything. So yes, if you pass "Hello World" to performSegueWithIdentifier:sender: as the sender value then this will be the sender in prepareForSegue:sender:

In terms of the order of operations:

  1. performSegueWithIdentifier:sender is called, either by your code or as a result of an action on a UI element
  2. If your view controller implements shouldPerformSegueWithIdentifier:sender: then this function is called. If this function returns false then the segue is cancelled
  3. The segue object and destination view controller object are created
  4. If your view controller implements prepareForSegue:sender: then this function is called.
  5. Once prepareForSegue:sender: returns, the segue completes.

Swift: performSegueWithIdentifier during unwind not working

In VC1 you need a function:

@IBAction func unwindToVC1(segue:UIStoryboardSegue) {
}

Then in your storyboard ctrl drag from the yellow view controller icon to the Exit icon and select unwindToVC1: from the pop up

Give the unwind segue an identifier, say unwindToVC1

Now, in VC2, create your button touchUpInside handler:

func buttonTapped(sender:UIButton) {
self.performSegueWithIdentifier("unwindToVC1")
}

when you set up your button programatically, add this method as the action handler:

button.addTarget(self, action: "buttonTapped:", forControlEvents: .TouchUpInside)

How to call performSegueWithIdentifier from xib?

The problem is that your UIView subclass is calling viewController().goToSecond(). That's not doing what you think it is. The viewController() isn't referencing the view controller that loaded your custom view. It's instantiating a second, orphaned instance of that class (not connected to any storyboard) and therefore cannot find the segue.

If you're really going to have this custom UIView subclass initiate a segue, you need to pass a reference to your original view controller to the custom view. So add a property to the custom view subclass that can hold the reference to its view controller, and when the view controller instantiates this custom view, it has to set that property.


For example:

import UIKit

protocol CustomViewDelegate: class { // make this class protocol so you can create `weak` reference
func goToNextScene()
}

class CustomView: UIView {

weak var delegate: CustomViewDelegate? // make this `weak` to avoid strong reference cycle b/w view controller and its views

@IBAction func toSecondButton(sender: AnyObject) {
delegate?.goToNextScene()
}

}

And then

import UIKit

class ViewController: UIViewController, CustomViewDelegate {

override func viewDidLoad() {
super.viewDidLoad()

let myCustomView = NSBundle.mainBundle().loadNibNamed("customView", owner: self, options: nil)[0] as! CustomView
myCustomView.delegate = self

// ... do whatever else you want with this custom view, adding it to your view hierarchy
}

func goToNextScene() {
performSegueWithIdentifier("toSecond", sender: self)
}

...

}

Swift performSegueWithIdentifier shows black screen

I've build your app and everything works, maybe you've missed something, here is my solution (Note: Code is in Swift 3.0, but should be easy to adopt it to Swift 2.*):

The storyboard:

Sample Image

Set the segueToTraits identifier:

Sample Image

Set the TraitViewController class as custom class in the storyboard:

Sample Image

The view controller with the buttons:

import UIKit

class ViewController: UIViewController {

let boyGender = "boy"
let girlGender = "girl"
var selectedGender: String?

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueToTraits"{
if let gender = self.selectedGender {
let traitVC = segue.destination as? TraitViewController
traitVC!.gender = gender
}
}
}

func sendGenderToTraitsView(gender : String?){
performSegue(withIdentifier: "segueToTraits", sender: self)

}

@IBAction func button1(sender: UIButton) {
selectedGender = boyGender
self.sendGenderToTraitsView(gender: selectedGender)
}

@IBAction func button2(sender: UIButton) {
selectedGender = girlGender
self.sendGenderToTraitsView(gender: selectedGender)
}

}

The trait view controller:

import UIKit

class TraitViewController: UIViewController {

var gender: String = ""

override func viewDidLoad() {
super.viewDidLoad()

print("gender: \(gender)")
}

}

Result:

Sample Image

You can find the sample project here

performSegueWithIdentifier is being skipped *SWIFT

You should move your code into the viewWillAppear or viewDidAppear method.
Then it should use properly.

But now the view flickers a short time. To remove that flickering, just hide the view in your viewWillApear method:

self.view.hidden = true

Also the viewDidLoad method doesn't get called everytime the view appears but only the first time it loads. If you for example perform a segue and return back to the view, it doesn't load again but only calls viewWillAppear and viewDidAppear again.

performSegueWithIdentifier Not Working - Swift

That's because you can't push view controller without UINavigationController. Please put UINavigationController or please set segue Kind "Modal" not "Push"



Related Topics



Leave a reply



Submit