Prepare for Segue in Swift

Prepare for Segue in Swift

This seems to be due to a problem in the UITableViewController subclass template. It comes with a version of the prepareForSegue method that would require you to unwrap the segue.

Replace your current prepareForSegue function with:

override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "Load View") {
// pass data to next view
}
}

This version implicitly unwraps the parameters, so you should be fine.

Swift how to trigger prepare for segue before target view load?

What I would do first is to DELETE ❌ the segue you've probably created by drag and drop from the button on VC1 to VC2. Replace it by a regular segue which is not attached to any UI component so that you can trigger it manually in code (from its identifier, don't forget to provide one). It will allow you to first perform some asynchronous code, and only when getting the callback trigger the navigation (if data fetch is successful).

To create such a segue:

  1. click on your VC1 in the storyboard => A small rectangle with icons should be now displayed right above the VC1
  2. Ctrl + drag from the yellow icon (probably at the most left of that rectangle) to the VC2 (on main view, does not rally matter where you drop it as long as it is on VC2)
  3. Provide identifier after having clicked on the newly created segue so that you can trigger it from code

That was for the segue, but now, when to trigger it?

  1. Create an an @IBAction on the button which is suppose to trigger the fetch + navigation (or equivalent, like didSelectRowAtIndexPath)
  2. This IBAction should call another method like the following:
private func fetchPostingAndNavigateIfSuccessful() {
// Should probably first set the activity indicator to `.startAnimating()`
let docRef = db.collection("Posting").getDocuments() { [weak self] querySnapshot, error in
// Should probably set the activity indicator to `.stopAnimating()`
guard error != nil,
let documents = querySnapshot?.documents else {
print("error getting documents") //probably a good place to display an alert
return
}
let postingsData = documents.map { $0.data() }
self?.performSegue(withIdentifier: "NavigateToPostingsSegue", sender: postingsData)
}
}

Your prepare for segue would then look like that:


override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if let postingListTableViewController = segue.destination as? PostingListTableViewController,
let postingsData = sender as? [[String:Any]] {
postingListTableViewController.updatedPostings = postingsData
}
}

Performing Segue to a new viewcontroller - prepare for segue fails swift 5

you need to create separate values for each of the elements you wish to add and then use them in the second view controller

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
let cell = collectionView.cellForItem(at: indexPath)
collectionView.deselectItem(at: indexPath, animated: true)

performSegue(withIdentifier: "addProductSegue", sender: cell)
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if let nextViewController = segue.destination as? AddProductsViewController
{
let productCell = sender as! ProductCell

nextViewController.productNameText = productCell.product!.Name
nextViewController.priceForKgText = "\(productCell.product?.priceForKg ?? 0.0)"
nextViewController.productImageImage = productCell.productImageView.image
}
}

And in the second ViewController have:

import UIKit

class AddProductsViewController: UIViewController
{
@IBOutlet weak var productName: UILabel!
@IBOutlet weak var priceForKg: UILabel!
@IBOutlet weak var productImage: UIImageView!
//The elements you will reference in your prepare for segue
var productNameText = ""
var priceForKgText = ""
var productImageImage : UIImage?
override func viewDidLoad()
{
super.viewDidLoad()
//Call the function
setupViews()
}

func setupViews(){ //create a function that handles the ui update once the objects are initialized
productName.text = productNameText
priceForKg.text = priceForKgText
guard let image = productImageImage else {
return
}
productImage.image = image
}

@IBAction func addProduct(_ sender: UIButton)
{
self.navigationController?.popViewController(animated: true)
}
}

Swift Prepare(for: segue) not called

You are calling performSegue on self.navigationController, so it's the navigationController.prepareForSegue that will be called, not the one in your VC. You should reconnect the segue to your VC in the storyboard, give it the identifier, and call:

self.performSegue(...)

Swift 3 - Prepare Segue

Replace your code with the following, it will not crash at least.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "HistorySegue" {
if let viewController = segue.destination as? HistoryController {
if(barcodeInt != nil){
viewController.detailItem = barcodeInt as AnyObject
}
}
}
}

Segue specific value in prepare for segue

There are two ways you could handle this:

Use the sender and set the button's tag value

The sender in prepare(for:sender:) is the button that was pressed, so you can set unique tag values for your 2 buttons and then check that:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let c2 = segue.destination as? twoViewController else {return}
if (sender as? UIButton)?.tag == 1 {
c2.ss = textfield.text
}
}

Set identifiers for the segues and check them in prepare(for:sender:)

Since you have two segues, click on the segue arrows in the Storyboard and set their identifiers in the Attributes Inspector. You could set the segue identifier for the top button to "sendTextField" and then check for that in prepare(for:sender:):

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let c2 = segue.destination as? twoViewController else {return}
if segue.identifier == "sendTextfield" {
c2.ss = textfield.text
}
}

Prepare For Segue on return

prepareForSegue is called if in Interface Builder a segue is connected

  • from a table/collection view cell to a destination view controller and the cell is tapped.
  • from a source view controller to a destination view controller and performSegue(withIdentifier:sender:) is called in the source view controller.

It's not called when a view controller is going to be presented with pushViewController

In your case assign the callback after instantiating the controller in showDatePicker, prepare(for segue is not needed.

func showDatePicker(){
let vc = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(withIdentifier: "DatePickerVC") as! DatePickerViewController
vc.callback = { result in
print(result)
print("Data")
// do something with the result
}

self.navigationController?.pushViewController(vc, animated: true)
}


Related Topics



Leave a reply



Submit