App crashes when presenting view controller - swift

I modally present a view controller, and then present an activity view controller. However when I do, the app crashes with error:
libc++abi.dylib: terminating with uncaught exception of type nsexception ios 10 "self.present"
This is what causes the app to crash:
let vc = UIActivityViewController(activityItems: [shareText], applicationActivities: [])
self.present(vc, animated: true, completion: nil)
I modally present the view controller with just a segue
self.performSegue(withIdentifier: "showContainer", sender: nil)

Related

Can't present view controller

I have a function that checks if the user is logged in. If the user is not logged in I want to present a login view controller. But as I mentioned in the title, the view controller is not shown. In addition, the initial view controller is not the login view controller (which is set in a storyboard and is a tab bar view controller). In fact, that view controller is in a different storyboard. Is that the problem?
private func validateAuth(){
if FirebaseAuth.Auth.auth().currentUser == nil {
let storyboard = UIStoryboard(name: "LoginAndRegisterStoryboard", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "LoginViewController")
self.present(vc, animated: true, completion: nil)
}
}
I tried to set the breakpoint to the function. The debugger says that the function is executed but the view controller is not shown. Any solutions?
And yes, the function is called.

Issue popToRootViewController when dismissing view controller

On dismiss of a .formsheet I need to perform a poptoviewcontroller currently I am presenting the view controller by doing the following:
let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "test") as! TestVC
let navigationController = UINavigationController(rootViewController: controller)
navigationController.modalPresentationStyle = .formSheet
self.present(navigationController, animated: true, completion: nil)
Attempting to dismiss and popToRootViewController underneath is not working
self.navigationController?.dismiss(animated: true, completion: {
print("Dismissing")
self.navigationController?.popToRootViewController(animated: true)
})
The dismiss is working, but it does not popToRootViewController.
When you're accessing the navigationController in your completion, you're accessing the same navigationController you've just dismissed, and not the "root" one.
Here's one of the ways you can access the navigation controller you're interested in and pop to root from it:
let presentingVC = self.presentingViewController
self.navigationController?.dismiss(animated: true, completion: {
print("Dismissing")
presentingVC?.navigationController?.popToRootViewController(animated: true)
})

How can I add a segue identifier to a programmatically modal transition?

I have a controller which is in the Main storyboard. When I click on a button, I call the displayBorneDetailsAction() action, it presents a modal view from another storyboard.
I would add a Segue identifier when I present my modal to pass data from my main view controller to my modal view controller (with prepareForSegue), but I don't know how to do it.
I tried to use performSegue(withIdentifier:), but it doesn't present the modal in the same way.
#IBAction func displayBorneDetailsAction(_ sender: Any) {
// open the modal of a borne
let storyboard : UIStoryboard = UIStoryboard(name: "Borne", bundle: nil)
let vc: BorneVC = storyboard.instantiateViewController(withIdentifier: "BorneVC") as! BorneVC
let navigationController = UINavigationController(rootViewController: vc)
navigationController.modalPresentationStyle = UIModalPresentationStyle.overFullScreen
navigationController.edgesForExtendedLayout = []
self.present(navigationController, animated: true, completion: nil)
}
You cannot add an identifier to a programmatical segue, since you are able to access the instance of the controller that is being presented. Simply do anything you want with the controller in the function where you present it.

App crashing when instantiating ViewController from different storyboard

I'm writing in Swift 3 (latest Xcode)
I'm controlling, if the user is logged in (async tasks checking parameters between device and database).
If the response says, that the device is invalid, I'm showing the login screen. Looks like this:
extension UIViewController {
func forceLogin() {
let storyboard = UIStoryboard(name: "Login", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "LoginViewController")
let navController = UINavigationController(rootViewController: controller)
self.present(navController, animated: true, completion: nil)
}
}
Login storyboard looks just like this.
When user successfully logs in, the function starts:
DispatchQueue.main.async {
self.dismiss(animated: true, completion: nil)
}
The dismissal may happen in first and second ViewController.
Imagine the situation:
User logs in and comes back to main application after dismissing 2nd VC
Device is being deleted from DB
After check, user needs to log in again
forceLogin() and...
libc++abi.dylib: terminating with uncaught exception of type NSException
It happens when self.present(navController, animated: true, completion: nil) is used.
I have some ideas what may cause the crash but I'm not sure:
Creating navigation controller in code instead in storyboard
Dismiss is not enough - storyboard somehow stays in memory and can't be instantiated again
What can cause the problem and how can I avoid crashing?
If any more info is necessary, please ask.
I always forget this. Remeber to place your interface tasks like this:
DispatchQueue.main.async {
self.present(navController, animated: true, completion: nil)
}

Swift - Trying to set up a share button

I'm trying to set up a share button from a time I previously coded it. I must be missing something, but I'm not sure what. Can you help? This is on a different view controller than the main one.
import UIKit
class MoreViewController: UIViewController, UITabBarDelegate, UITextFieldDelegate {
#IBAction func shareKnockingBuddy(_ sender: AnyObject) {
let messageToSend = "Here is a message. \(doorsKnocked)"
let vc = UIActivityViewController(activityItems: [messageToSend], applicationActivities: nil)
self.present(vc, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Here's my error: On the App delegate it's "Thread 1: signal SIGABRT". On the message thingy on the bottom, it says "* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIViewController shareKnockingBuddy:]: unrecognized selector sent to instance 0x7fe282c02eb0'
* First throw call stack:"
Notice the error is about UIViewController and not your MoreViewController class. This means you did not set th proper class name for the view controller in your storyboard. Change it to MoreViewController.