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

I have created a ViewController with a view and a button. I have declared the button as an outlet and as an Action in the viewcontroller. Additionally I am passing the data of the first Viewcontroller to the second Viewcontroller with a segue. When I click the cancel button which executes a segue back to the first viewcontroller I get the error
Thread 1: signal SIGABRT.
The error is shown in the prepare function which is passing the data. I have already controlled the connection inspector. I don't know what is wrong with my code.
here is my code:
#IBAction func cancelButton(_ sender: Any) {
performSegue(withIdentifier: "backToFirstScreen", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let tableViewVC = segue.destination as! tableViewController
tableViewVC.passwordNotes3 = passwordNotes2
tableViewVC.passwordCategory3 = passwordCategory2
tableViewVC.passwordStrings3 = passwordStrings2
}

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.

Related

Make a segue to a tableview controller from a view controller

I am trying to make a segue to a table view controller when a button is tapped in my view controller programmatically. Here is my code:
#objc func editProfileButtonAction(sender: UIButton!) {
print("ButtonTapped")
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let identifier = segue.identifier {
if identifier == "EditProfile" {
var editProfileTableViewController = segue.destination as! EditProfileTableViewController
editProfileTableViewController = self
}
}
}
}
I really could use some help. I also need to make a segue to a collection view controller using a button in the same view controller.
Okay to clarify that. There is no way to create a segue programmatically. Segues are the arrows on storyboard linking from one to another VC. They are called with: performSegue. This calls the function prepare.
If you want to show a new VC when hitting a button (without segue), then you use the present(VC(), animated: true, completion: nil) } inside the button function. The VC is presented modally.
#objc func editProfileButtonAction(sender: UIButton!) {
print("editProfileButtonAction")
present(EditProfileTableViewController(), animated: true, completion: nil)
}
Make sure, that the segue in the Storyboard has exactly the identifier: "EditProfile". Normally I'm writing identifiers with lower letter in the beginning. You also need to prepare for Segue. For example set the delegate:
// Set ViewController class as the delegate of the EditProfileTableViewControllerDelegate protocol
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let identifier = segue.identifier {
if identifier == "EditProfile" {
let editProfileTableViewController = segue.destination as! EditProfileTableViewController
editProfileTableViewController = self
}
}
}
At one point in my coding time, I deleted all my storyboard because of too many error's that I could hardly solve. Now I'm doing it all programmatically. At first it was a bit hard to set up all the view's by myself but after all I'm very glad I'm not using storyboards anymore. For some stuff I need xib's, and for testing storyboard. Just if you're interested: the most iOS programmers are using storyboard, so it's okay if you go on with that.
The advantage of doing it all programmatically is that there are no segue's anymore. So just present, and on navigation VC's push, pop, ...

nothing happens on trying to dismiss popover viewcontroller Swift

I have a viewcontroller that is presented as popover when the user clicks on an ImageView.
The problem is, I added a button to dismiss it but when I tap on it nothing happens.
The code I have is:
#IBAction func onCloseTapped(_ sender: Any) {
presentedViewController?.dismiss(animated: true, completion: nil)
}
I've also tried dismiss(animated: true, completion: nil) and other methods, but still nothing.
Can anyone tell me what I am doing wrong?
Edit: Posting a screenshot:
Edit 2: I'm presenting it from the storyboard. I've added a gesture recognizer on the image, then added segue from the storyboard that says present as popover, then anchor to the image.
it won't work because when you show as popover, the viewController doesn't have the navigationController. You have to create a delegate method and use the dismiss function on the viewController that make the call to the popover.
Here an exemple:
make the popover delegate, in the popover viewController:
protocol PopoverViewControllerDelegate: NSObjectProtocol {
func dismiss()
}
then you create a delegate variable and call when the button is tapped:
var delegate: PopoverViewControllerDelegate?
#IBAction func onCloseTapped(_ sender: Any) {
delegate?.dismiss()
}
Now in the viewController that call the popover you override the prepare for segue method to set the popover delegate:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "popover" {
if let vc = segue.destination as? PopoverViewController {
vc.delegate = self
}
}
}
Now you just need to use the delegate to dismiss your popover viewController:
extension ViewController: PopoverViewControllerDelegate {
func dismiss() {
navigationController?.dismiss(animated: true, completion: nil)
}
}
Don't forget to put the identifier for you segue, the identifier that we use is this = "popover"
Hope that help you.

How to show activity indicator while passing between view controller

Lets say I have 2 ViewControllers, in my MainViewController I have a button which performs a segue to SecondViewController. When button tapped, I'm saving some initial data to coreData, so it takes some time.
Here is the thing that I want to do;
While passing between ViewControllers, I want to show ActivityIndicator, but its starts after SecondViewController is opened. Could you help me? I'm new to Swift.
Here is the code I used in my MainVC:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "SecondViewController") {
SwiftSpinner.show("Loading") // Act. indicator found on github
willRunOnce() // Here Im saving data to CoreData
SwiftSpinner.hide()
}
}
Instead of adding code of ActivityIndicator in prepare(for:sender:) method you need to call it in the Button action and after that call performSegue(withIdentifier:sender:) method.
#IBAction func onBtnSkip(_ sender: UIButton) {
SwiftSpinner.show("Loading") // Act. indicator found on github
willRunOnce() // Here Im saving data to CoreData
SwiftSpinner.hide()
//Now performSegue
self.performSegue(withIdentifier: "identifier", sender: nil)
}

How can I call a new UIViewController within in UITabcontroller

I have a UITabContrroller(here WelcomeViewController) and when I click a button on one of it's tab item page, it shows a popover(PopViewController) with another button for displaying a new page (SecondPageViewController), but should show same tabs in the parent UITabContrroller.
First I tried the option Sequee from the button of PopViewController and uncomment the prepareForSegue, but it did not work.
Later I tried to connect WelcomeViewController(where Tabbar resides) with seguee to SecondPage.
button code is as follows:
#IBAction func goToCarerUpdateProfile(sender: UIButton) {
let careerPageView = self.storyboard?.instantiateViewControllerWithIdentifier("WelcomeViewControllerIdentifier") as! WelcomeViewController
careerPageView.performSegueWithIdentifier("pushToCarerUpdateProfileSegue", sender: self)
}
This code calls the prepareForSegue function of WelcomeViewControllerIdentifier, but there is no Second page visible.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "pushToCarerUpdateProfileSegue" {
print("This portion working")
let svc = segue.destinationViewController as? CarerUpdateProfileViewController
}
How can I call a new UIViewController within in UITabcontroller ? The conditionn is the new View should have the same tabs as previous.

How to destroy instance of view controller after performing segue

I use performSegueWithIdentifier to navigate between views controllers
I have a tableView with multiple rows, when a row is actioned, i call a webViewController to play selected ressource with segue
performSegueWithIdentifier("Play", sender: nil)
Associate with :
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "Play") {
let detailVC = segue.destinationViewController as! WebViewController
detailVC.courseToPlay = self.courseToPlay
}
}
And, on WebViewController, i've a button to goBack on the list, whose i want to destroy instance of webViewController on goBack
I've not NavigationController in my storyBoard, so, this line doesn't work
navigationController.popViewControllerAnimated(true)
I use segue again to goBack :
performSegueWithIdentifier("closePlayer", sender: nil)
But each segue action instance a new view controller and they're never really free from memory, they seems to just be hiddens
eg : in Safari debugger i can see a lot of page and i can always interact with these in console
How to properly 'destroy' a view when scene change
Swift3:
self.dismiss(animated: true, completion: nil)
Hope it can help you.
Thanks
If it is a modal segue you can use
dismissViewControllerAnimated(true, completion: nil)
To dismiss the webViewController instead of another segue