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:
- click on your VC1 in the storyboard => A small rectangle with icons should be now displayed right above the VC1
- 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)
- 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?
- Create an an @IBAction on the button which is suppose to trigger the fetch + navigation (or equivalent, like didSelectRowAtIndexPath)
- 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
Swift Get Request With Parameters
How to Play Audio in Background With Swift
How to Catch "Index Out of Range" in Swift
Get the Current Scroll Position of a Swiftui Scrollview
How to Pass Data Between View Controllers in Swift
Didselectrowatindexpath Not Working, Swift 3
Uitableviewcell, Show Delete Button on Swipe
Difference Between Uiviewcontentmodescaleaspectfit and Uiviewcontentmodescaletofill
How to See Saved Nsuserdefaults
How to Simultaneously Satisfy Constraints, Will Attempt to Recover by Breaking Constraint
Delete Keychain Items When an App Is Uninstalled
How to Use Generic Protocol as a Variable Type
Set the Maximum Character Length of a Uitextfield in Swift
Interface Builder: What Are the Uiview's Layout iOS 6/7 Deltas For
Unwind Segue Not Working in iOS 8
Uipageviewcontroller Gesture Recognizers
How to Determine Whether Code Is Running in Debug/Release Build