Thread Error in Ibaction While Overriding Prepareforsegue Function

How to get unwind segue to work between along side a regular segue in the same view controller?

This function in MoonViewController:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let des = segue.destination as! JupiterViewController //<- ERROR HERE

if (segue.identifier == "toJupiterView")
{
print("Went to Jupiter")
}
}

is called both for regular segues and unwind segues. When you are segueing to JupiterViewController then segue.destination is indeed of type JupiterViewController. But when you are unwinding to ViewController, segue.destination is of type ViewController.

In this second case, the force cast as! JupiterViewController crashes because the type is wrong.

One way to fix that is to move the declaration of des inside of the if when you have identified the destination:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toJupiterView"
{
let des = segue.destination as! JupiterViewController
print("Went to Jupiter")
}
}

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
}
}

When I go back to menu, the App crashes (Thread 1: signal SIGABRT)

Most probably this happens because you put AV code inside of viewWillAppear. This method executed every time you enter the view (in your case it's when the app starts and when the user gets back to the main menu).

This line definitely isn't meant to be executed multiple times:

try session.addInput(AVCaptureDeviceInput(device: device))

And this one:

session.startRunning()

And this:

self.view.insertSubview(blurView,at:1)

A quick fix would be to put all of this logic in a dedicated function and add a flag to run it only once. Something like that:

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
addBlur()
}

var didAddBlur = false
func addBlur() {
if didAddBlur {
return
}

didAddBlur = true

//Your code
}

@IBAction to performSegue

Use the following code:

ViewController.swift

 import UIKit

class ViewController: UIViewController, SecondViewControllerProtocol{
@IBOutlet weak var dataLabel: UILabel!

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

@IBAction func navigateToSecondViewControllerOnButtonClick(_ sender: AnyObject) {

let secondVC: ViewController2 = storyboard?.instantiateViewController(withIdentifier: "viewcont2") as! ViewController2
secondVC.delegate = self
self.navigationController?.pushViewController(secondVC, animated: true)
}

func saveData(data: String){
dataLabel.text = data
}

}

ViewController2.swift

 import UIKit

protocol SecondViewControllerProtocol {
func saveData(data: String) // this function the first controllers
}

class ViewController2: UIViewController {

var delegate: SecondViewControllerProtocol?

@IBOutlet weak var dataTextField: UITextField!

override func viewDidLoad() {
super.viewDidLoad()

// Do any additional setup after loading the view.

}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

@IBAction func saveButtonClicked(_ sender: AnyObject) {
delegate?.saveData(data: dataTextField.text!)
}
}

Storyboard screenshot:

enter image description here

Please check my GitHub link below to test sample:

https://github.com/k-sathireddy/PassingDataThroughSegue

how can i fix the error Thread 1: signal SIGABRT?

I think the problem here is that you havent created a "backToFirstScreen" segue that starts in the second view controller and ends in the first viewcontroller.

Using a segue to go back to the first screen is slightly taboo; I would replace

performSegue(withIdentifier: "backToFirstScreen", sender: self)

with

self.dismiss(animated: true, completion: nil)

or if you're using a navigation controller

self.navigationController?.popViewController(animated: true)

This allows you to dismiss the current viewcontroller youre looking at and return to the view controller which presented it without having to create a segue that goes in reverse. Just make sure you have a segue that goes from the first view controller to the second view controller in that order.

NSDictionary has value of none

I fixed the issue by simple giving the uid of the otheruser NSDictionary to a new variable which I created in the viewdidLoad.
This way I do not face any issues regarding unwrapping optionals later on.



Related Topics



Leave a reply



Submit