I get the error:
"Unbalanced calls to begin/end appearance transitions for ”.
In my app you start at a tableViewController, if you click the photo icon at the bottom the camera pops up and when you have taken a photo you go through a navigationController into the editing viewController. From here if you click the image you are sent to the preview viewController.
My problem is if I click "New Photo" when editing an existing item it works fine, but if I click "New Photo" on an item i have just created (and not yet saved) I'm sent all the way back to the initial tableViewController
My code looks like this:
// Called when the user finishes taking a photo.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
// The info dictionary contains multiple representations of the image, and this uses the original.
image = info[UIImagePickerControllerOriginalImage] as? UIImage
// Dismiss the picker.
dismiss(animated: false, completion: nil)
performSegue(withIdentifier: "unwindToExpenseView", sender: self)
}
In my editing viewController
#IBAction func unwindToExpenseView(sender: UIStoryboardSegue) {
if let ImagePreviewer = sender.source as? ImagePreviewViewController {
photoImageView.image = ImagePreviewer.image
}
}
Try to performSegue in completion of dismiss(animated:).
self.dismiss(animated: false) {
performSegue(withIdentifier: "unwindToExpenseView", sender: self)
}
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)
Basically I have tab bar controller with two tabs, each holds a separate navigation controller, each with a couple of views (see below).
In the "top" navigation controller (held in the right tab), I can choose an image, and then am taken to the rightmost screen to preview the image...
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerEditedImage] as? UIImage {
let previewController = self.storyboard?.instantiateViewController(withIdentifier: "previewVC") as! PreviewViewController
previewController.img = image
previewController.navigationItem.setHidesBackButton(true, animated: false)
self.navigationController?.pushViewController(previewController, animated: true)
self.dismiss(animated: true, completion: nil)
}
}
...where I tap "post". This uploads the image and calls self.tabBarController?.selectedIndex = 0
That simply takes me to the image feed, which is in the "bottom" navigation controller (left tab). So far so good. However, the preview screen is still displayed in the "right" tab, when I need the upload screen to be displayed after I post.
If I call self.dismiss(animated: true, completion: nil) when I tap post, the entire navigation controller is dismissed and I'm taken back to the login screen.
So I'm trying to dismiss the preview controller so the upload controller is shown as the default view in the right tab, without dismissing the entire stack in that navigation controller.
How can I do this?
If you use navigation controllers to add view controllers to the navigation stack (push), you can remove them by calling a pop function. When you present view controllers modally, you call dismiss to remove the view controller.
The delegate function gives you the (image picker) view controller and you should dismiss that, not the view controller that is the delegate (usually the presenting view controller). Maybe try something like this:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerEditedImage] as? UIImage {
let previewController = self.storyboard?.instantiateViewController(withIdentifier: "previewVC") as! PreviewViewController
previewController.img = image
previewController.navigationItem.setHidesBackButton(true, animated: false)
self.navigationController?.pushViewController(previewController, animated: true)
picker.dismiss(animated: true, completion: nil)
}
}
I have an action button in my iOS application (using Swift 3), which I guess is technically a toolbar item.
I presently disable the button in viewWillAppear() with
actionButton.isEnabled = false
I then try to enable it after an image has been selected:
func imagePickerController(_: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
imageView.image = image
imageView.contentMode = .scaleAspectFit
}
dismiss(animated: true, completion: nil)
actionButton.isEnabled = true
print("selected an image in picker")
}
And I can see that my print statement occurs as well as the image being selected and activity view controller dismissing, just as expected. HOWEVER, my actionButton stays disabled.
Any ideas why? I'm very new to Swift!
viewWillAppear() is called every time, before your view controller loads. When you dismiss your imagePicker, and go back to presenting your original viewController that viewWillAppear() would be called again, and it would override your actionButton.isEnable = true to being false again. If I were you, I would disable the button in viewDidLoad(), which is called only once.
try to execute the code that changes the UI in the main thread like this:
DispatchQueue.main.async {
actionButton.isEnabled = true
}
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)
})
I have implemented the camera roll when I click the middle button just like in instagram using the function ShouldSelectViewController. And if I hit cancel, it goes back to the tab before. The problem I m having now is that, I would like to show another view controller with the selected image. Is there any function that can me to solve this?
Thank you
If you're using UIImagePickerController, there is a delegate method you can implement to handle what happens after a picture is selected.
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
//do something with the image
}
}
You can segue to another view controller in this method via the regular patterns. For example, let's say you decide to put the image in another view controller called AnotherViewController.
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
let vc = storyboard!.instantiateViewControllerWithIdentifier("anotherViewController") as! AnotherViewController
vc.imageToDisplay = image
presentViewControllerAnimated(vc, animated: true)
}