I'm trying to do the following:
User presses button
UIImagePickerController pops up
User selects image
UIImagePickerController is dismissed
Segue into another ViewController
As of now, I have it set up that when the user presses a button, a UIImagePickerController is initialized and presented with presentViewController. It is also delegated to the class that this button is linked to as well. After the user picks an image, imagePickerController is called, and dismissViewControllerAnimated is also called. Then, performSegueWithIdentifier is called. However, this last step throws the following warning, and then does not segue:
2016-09-15 03:45:44.870 Food Diary[9941:1540144] Warning: Attempt to present
on whose view is not in the window hierarchy!
I am very new to Swift and iOS development, what does this mean and how do I fix it?
Perform segue on completion of dismiss of UIImagePickerController
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
// your code
self.dismissViewControllerAnimated(true, completion: {
self.performSegueWithIdentifier("SegueIdentifier", sender: self)
})
}
Note: With sender I have passed current Controller object you can any object that you want.
Try to using these two lines code during presenting and dissmising your view controller
Presenting :
self.view.window.rootviewcontroller.presentViewController("yourVC",animated:true, nil)
Dissmising :
self.view.window.rootViewController.dismissViewController(animated:true completion:nil)
It stays on the same ViewController because the UIImagePickerController is still in view hierarchy a the d second ViewController cannot be added on top of UIImagePickerController. To fix, you need to wrap your segue in the completion of UIImagePickerCopntroller dismissal like this:
self.dismiss(animated: true, completion: {
self.performSegue(withIdentifier: "StartToMain", sender: nil)
})
Related
I would like to perform a segue just after the user chooses an image (by clicking on the image view).
I have already checked the segue id and successfully managed to connect both view controllers.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
// Executed when we select an image from the photo library.
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
// Sets the image to the image view (not really relevant because
// we push the user to the DetailVC, but let's leave it).
self.imageView.image = image
// Closing the image picker.
self.dismiss(animated: true, completion: nil)
// Performing segue (It doesn't perform!).
print("It gets to this point, but doesn't perform.")
self.performSegue(withIdentifier: "showDetail", sender: nil)
}
}
The program sets the image to the image view, gets to that print statement just after the "perform" function, but the segue is not performed.
in storyboard select the view controller which has the imageview, at the top there is yellowcircle right click drag from there to the view controller you want to segue to and give its identifier an ID = “segueID”
then edit your didfinishpicking method like this
if let img = info[.originalImage] as? uiimage{
myimageview.image = img
dismiss(animated: true) {
self.performSegue(withIdentifier: “segueID”, sender: self)}}
I believe the problem lies that you are dismissing your view/view controller before performing segue
// Closing the image picker.
self.dismiss(animated: true, completion: nil)
Have you tried:
Setting the sender to self?
Making sure that your segue is the correct type. (I know you checked the name and you probably would have gotten an error if you got the name wrong, in this case I mean "push" vs "show detail" etc)
Adding a prepareForSegue function to make sure that the segue is actually getting called
Building up on #Loren Rogers answer:
// Closing the image picker.
self.dismiss(animated: true, completion: nil)
You're not actually dismissing the UIImagePickerController. Like Loren mentioned, you're dismissing the ViewController. This is because self is a reference to the ViewController.
Replace self with picker like so:
// Closing the image picker.
picker.dismiss(animated: true, completion: nil)
I'm totally newbie level with swift and having a question. so, I created a navigation controller for my modal and having my modal opened up from my first view controller with segue (Button2). The question is, how to get back to my first view controller from Modal View
You can use the dismiss method to dismiss a specific ViewController.
The question is how you want to dismiss the ViewController presented modally? With a button? Tap anywhere in the View? Tap on a little cross button?
For example if you have an UIButton to dismiss:
#IBAction func didTapClose(_ sender: UIButton) {
dismiss(animated: true, completion: nil)
}
If the segue is "present modally", you can dismiss the view controller through this line :
dismiss(animated: true, completion: nil);
Else If the segue is "show", you can dismiss the view controller through this line :
navigationController?.popViewController(animated: true);
In this case, be sure that you embedded your ViewController to a navigationController in your storyboard. If your ViewController is not embedded to a navigationController and you have used show segue, you should use dismiss(animated: true, completion: nil) to return to previous page.
Also there is other ways to return to previous pages (e.g., unwind segue)
Good luck.
I have this situation :
I have a first view controller , when tap on button in it I open in modal mode another view controller , in this view controller when I tap another button I open in modal view another view controller and in it there is a button and when I tap on it I want to go to first view controller without re-initialize it.
How do I do it?
This is the perfect situation for an unwind segue.
Put this in your first viewController (the one you want to return to):
#IBAction func backFromVC3(_ segue: UIStoryboardSegue) {
print("We are back in VC1!")
}
Then in the Storyboard in your 3rd viewController, control-drag from your button to the exit icon at the top of the viewController and choose backFromVC3 from the pop-up.
Now, when the user presses the button in VC3, both VC3 and VC2 will be dismissed and you will return to VC1.
If you are not using Storyboards, you can dismiss the viewControllers with code. Here is code for a button's handler to dismiss two levels of viewController:
func doDismiss(_ sender: UIButton) {
// Use presentingViewController twice to go back two levels and call
// dismissViewController to dismiss both viewControllers.
self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)
}
Thanks all for reply and edited my question :)
I found 2 line code to resolved my problem:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window!.rootViewController?.dismissViewControllerAnimated(true, completion: nil).
And that work well.
Thanks very much
My first view controller has a button, which triggers the #IBAction goTo2ndVc() which presents a second ViewController:
class FirstVC: UIViewController {
...
#IBAction func goTo2ndVc() {
let secondVc = SecondVC(label: "I am second vc.")
self.presentViewController(secondVc, animated: true, completion: nil)
}
When the button is pressed, the 2nd view controller is shown on screen. No problem.
In 2nd view controller, there is also a button which is used to go back to 1st view controller:
class SecondVC: UIViewController {
...
#IBAction func backToFirst(sender: AnyObject) {
print("go back ...")
self.navigationController?.popViewControllerAnimated(true)
}
}
I looked on internet, people suggest to use navigationController?.popViewControllerAnimated(true) to go back to previous controller. But when I press the go back button I can see the print message "go back ..." but the app doesn't go back to 1st view controller. WHY?
#IBAction func backToFirst(sender: AnyObject) {
print("go back ...")
self.dismissViewControllerAnimated(true, completion: nil)
}
In Swift 3
self.dismiss(animated: true, completion: nil)
you should not use navigation controller, because you didn't use it when you were adding the second view controller. that's why simply call dismissViewControllerAnimated method.
You have to use UINavigationController and its pop methods only when you add your view controllers via pushViewController method.
Familiarize yourself with the concept of navigation controller here: https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/NavigationControllers.html
there
the issue is very simple..
self.presentViewController(secondVc, animated: true, completion: nil)
the code will present second view, you are not pushing it.
self.navigationController?.popViewControllerAnimated(true)
the popViewController will pop back to the previous view controller from where it is been pushed.
So, there are two ways you can achieve what you want
1)If you want to present viewController then you have to dismiss the view controller to show previous view controller with
self.dismissViewControllerAnimated(true, completion: nil)
2)If you want to use PopToVewcontroller, then you have to push you second view controller instead of presenting it with
self.navigatioVonroller?.pushViewController(secondVc, animated: true)
If you want to return to the previous view controller, you can simply add:
[self dismissViewControllerAnimated:YES completion:nil];
to the button action method.
If this is added on the nav view controller present on every screen, I see no reason why it shouldn't work as it would always dismiss the most recently presented view.
In the first screenshot, LatestPost is set as Is Initial View Controller. When I press Camera tab, it launches the .Camera for UIImagePickerController. However when I hit "Cancel", it dismisses the current ViewController, and my tab bar goes missing as shown on the second screenshot.
The second screenshot is embedded inside a UINavigationController.
I quite certain that has got to do with dismissing my ViewController. The question here is how do I "de-initialized" my ViewController?
My codes as follow:
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
dismissViewControllerAnimated(true, completion: nil)
}
EDIT: Added Storyboard screenshot as requested.