I have a new iOS app in Swift where I'm trying to show the camera as soon as the app is launched. In my view controller I have a single UIView object which I try to fill with the camera.
The code in my view controller calls UIImagePickerController in the viewDidLoad method but nothing happens.
Here is the code, any idea why nothing happens? Isn't the camera supposed to open on app launch with this code?
import UIKit
class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
let imagePicker = UIImagePickerController()
#IBOutlet weak var imageViewer: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
if UIImagePickerController.isCameraDeviceAvailable( UIImagePickerControllerCameraDevice.Front) {
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.Camera
presentViewController(imagePicker, animated: true, completion: nil)
} else {
println("no front camera available")
}
// 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.
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
dismissViewControllerAnimated(true, completion: nil)
imageViewer.image = image
}
}
UPDATE: if I add a button to the storyboard, connect it to the code and put the code from viewDidLoad in it, the camera works when the button is clicked:
#IBAction func presentImagePicker(sender: AnyObject) {
if UIImagePickerController.isCameraDeviceAvailable( UIImagePickerControllerCameraDevice.Front) {
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.Camera
presentViewController(imagePicker, animated: true, completion: nil)
}
}
I know that the camera works, but how to make it work without having to press a button?
Here is the solution for you.
Put your code in viewDidAppear method this way:
override func viewDidAppear(animated: Bool) {
if UIImagePickerController.isCameraDeviceAvailable( UIImagePickerControllerCameraDevice.Front) {
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.Camera
presentViewController(imagePicker, animated: true, completion: nil)
}
}
This will load camera when your app start.
Trying to do it in viewDidLoad won't work because that is called after the view is first created, and the view isn't a subview of anything else at that point.
override func viewDidLoad() {
if UIImagePickerController.isCameraDeviceAvailable( UIImagePickerControllerCameraDevice.Front) {
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.Camera
presentViewController(imagePicker, animated: true, completion: nil)
}
}
Related
I'm trying to present the ImagePickerController modally. My button firing the present action is inside a subview of the main view.
When pressing the button, the ImagePicker view is showing and dismissing right away.
I tried the same with another button which resides in the main view, and it's working fine.
My button action code:
#IBAction func pressUploadProfilePhoto(_ sender: Any) {
picker.allowsEditing = false
picker.sourceType = .photoLibrary
present(picker, animated: true, completion: nil)
}
Class deceleration:
class ProfileVC: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let imagePicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
imagePicker.delegate = self
}
}
Delegate methods:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
profilePicImg.contentMode = .scaleAspectFill
profilePicImg.image = pickedImage
}
self.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
My Views hierarchy:
What am i missing?
Please Try the below code, may be your problem get resolved ->
1) Firstly add these Delegates in your Class.
class XYZ: UIActionSheetDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate
2) Create a variable ->
let imagePicker = UIImagePickerController()
3) Set imagePicker delegate in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
imagePicker.delegate = self
}
4) Write Delegate Methods for UIImagePicker
// MARK: - ImageView Controller Delegate Methods
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
imageviewProfile.contentMode = .scaleToFill
imageviewProfile.image = pickedImage
}
dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
5) Now your Action Method ->
#IBAction func pressUploadProfilePhoto(_ sender: Any) {
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
imagePicker.allowsEditing = false
imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary
imagePicker.modalPresentationStyle = .fullScreen
present(imagePicker, animated: true, completion: nil)
}
}
I have 2 UIViewControllers:
ViewController 'A' named 'RERUN_SETUP' with an UIImageView and ViewController 'B' named 'SelectPhotos' with an imagePickerController.
There is an empty transparent UIButton over the UIImageView in ViewController 'A', which pops up ViewController 'B' and allows the user to select adding a picture from Camera or from Photos. ViewController 'A' is declared in ViewController 'B', but when I try to change the UIImageView on ViewController 'A' from ViewController 'B', the app crashes with an error
fatal error: unexpectedly found nil while unwrapping an Optional value.
Below is my code, any help will be greatly appreciated :)
ViewController 'A'
class RERUN_SETUP: UITableViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIPopoverPresentationControllerDelegate {
//USER PICTURE
#IBOutlet weak var RERUNpictureIn: UIImageView?
//TRANSPARENT BUTTON OVER THE IMAGE VIEW
#IBAction func imageButton(sender: AnyObject) {
let popoverContent = self.storyboard?.instantiateViewControllerWithIdentifier("SelectPhotos")
popoverContent!.modalPresentationStyle = .Popover
popoverContent?.modalTransitionStyle = UIModalTransitionStyle.FlipHorizontal
var popover = popoverContent!.popoverPresentationController
if let popover = popoverContent!.popoverPresentationController {
let viewForSource = sender
popover.sourceView = self.view
popoverContent!.preferredContentSize = CGSizeMake(100,80)
popover.delegate = self
popover.permittedArrowDirections = .Any
}
self.presentViewController(popoverContent!, animated: true, completion: nil)
}
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
return UIModalPresentationStyle.None
}
ViewController 'B'
import UIKit
class SelectPhotos: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var savedImage = NSUserDefaults.standardUserDefaults().objectForKey("image")
var imageToSave = UIImage()
var otherController:RERUN_SETUP = RERUN_SETUP()
#IBAction func camera(sender: UIButton) {
let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.sourceType = UIImagePickerControllerSourceType.Camera
pickerController.allowsEditing = true
self.presentViewController(pickerController, animated: true, completion: nil)
}
#IBAction func photos(sender: AnyObject) {
let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
pickerController.allowsEditing = true
self.presentViewController(pickerController, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
self.dismissViewControllerAnimated(true, completion: nil)
self.imageToSave = image
otherController.RERUNpictureIn!.image = image
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
In View Controller B in your image picker delegate method save your image to nsuserdefault and in your viewconroller A get that image from nsuserdefault. and set the image.
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
let imageData = UIImagePNGRepresentation(image)
NSUserDefaults.standardUserDefaults().setObject(imageData!, forKey: "image")
NSUserDefaults.standardUserDefaults().synchronize()
}
and in your View Controller where you want to set the image
let imageData = NSUserDefaults.standardUserDefaults().objectForKey("image") as! NSData
imgView.image = UIImage(data: imageData)
The reason you are getting nil for RERUNpictureIn ImageView, is that it has not initalized yet for that empty object you have declare named otherController inside your SelectPhotos controller, Also that object will not helpful because the object you have create it not belongs to the object that is currently running with your application.
To send image to previous one you can use delegate/protocol for that.
First declare one protocol like this and implement with your RERUN_SETUP Controller
protocol ImageDelegate {
func getImage(image: UIImage)
}
Now implement it inside your
class RERUN_SETUP: UITableViewController, ImageDelegate, UIPopoverPresentationControllerDelegate {
//Your Code
//Implement method of ImageDelegate
func getImage(image: UIImage) {
self.RERUNpictureIn.image = image
}
}
Now add one object of ImageDelegate inside your SelectPhotos controller
import UIKit
class SelectPhotos: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var savedImage = NSUserDefaults.standardUserDefaults().objectForKey("image")
var imageToSave = UIImage()
var delegate: ImageDelegate?
#IBAction func camera(sender: UIButton) {
let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.sourceType = UIImagePickerControllerSourceType.Camera
pickerController.allowsEditing = true
self.presentViewController(pickerController, animated: true, completion: nil)
}
#IBAction func photos(sender: AnyObject) {
let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
pickerController.allowsEditing = true
self.presentViewController(pickerController, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
self.imageToSave = image
self.delegate.getImage(self.imageToSave)
self.dismissViewControllerAnimated(true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Note: Now inside RERUN_SETUP controller where you are creating object of SelectPhotos for presenting the view, just add one line before presenting the object.
objectOfSelectPhotosThatYouHvaeCreated.delegate = self
Typically, when I get this error, it has something to do with me having an extra "?" or "!" somewhere. Or that I'm missing one somewhere. Try messing around with those and see if it fixes your bug.
I am able to start the UIImagePickerController to make a picture:
func selectCamera(){
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.Camera;
imagePicker.allowsEditing = true
self.presentViewController(imagePicker, animated: true, completion: nil)
}
}
and with this function to choose from the saved pictures:
func selectPicture() {
let picker = UIImagePickerController()
picker.allowsEditing = true
picker.delegate = self
presentViewController(picker, animated: true, completion: nil)
}
I can either choose a image from my image gallery on the phone or take a picture.
But i want to choose one of the saved image gallery pics inside the camera view, how it is in the standard camera application. Is this possible?
If you want to have Gallery Pics inside camera view, you got to create a custom cameraOverlay view, which has a button to then open the saved pictures.
To make it faster, you can use a library like --> https://github.com/GabrielAlva/Cool-iOS-Camera
Or
You can also have a action sheet, asking user to select which option he wants.
Check this -> How to allow the user to pick a photo from his camera roll or photo library?
& this --> https://github.com/chroman/CRMediaPickerController
I am using this solution, without additional libraries.
First of all don't forget to delegate, UIImagePickerControllerDelegate, and navigation delegate. Those thigns needed only for imagePickerController.
Update, check function saveImageViewToAlbum, be sure that your imageView containt image, otherwise you probably will catch exception. Adds a photo to the saved photos album. The optional completionSelector should have the form:
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
Just created this project, and everything works on swift, iOS 9.3
import UIKit
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var choosenImageView: UIImageView!
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 openAlbum(sender: UIButton) {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
imagePickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self .presentViewController(imagePickerController, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
choosenImageView.image = image
self .dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func saveImageViewToAlbum(sender: UIButton) {
UIImageWriteToSavedPhotosAlbum(choosenImageView.image!, nil, nil, nil)
}
}
I useELCImagePickerController to select multiple photos. However when i select photos and click Done button its goes back to select an album page. Please help me so when i select photos it should back to viewController .
Here is code i using:
var picker = ELCImagePickerController(imagePicker: ())
#IBAction func ButtonIsclick(sender: AnyObject) {
picker.delegate = self
self.presentViewController(picker, animated: true, completion: nil)
}
func elcImagePickerController(picker: ELCImagePickerController!, didFinishPickingMediaWithInfo info:[AnyObject]!) {
self.dismissViewControllerAnimated(true, completion: nil)
}
func elcImagePickerControllerDidCancel(picker: ELCImagePickerController!){
self.dismissViewControllerAnimated(true, completion: nil)
}
EDIT: When i debug the code its never call the didFinishPickingMediaWithInfo function
Actually i face this problem because of wrongly set the delegate.
In my question i set delegate as
picker.delegate = self
Which is wrong . Right way is to set ELCImagepickerDelegate is
picker.imagePickerDelegate = self
I solved it - find below the complete final working code -
The problem was I had to add ELCimagepickerdelegate to the class to be as:
class ViewController: UIViewController, UINavigationControllerDelegate, ELCImagePickerControllerDelegate {
however I used to get an error (Type viewcontroller does not conform to protocol) every time I do this, so the solution was to ignore this error until I add the 2 delegate methods below in my code (that stopped the error, which was very confusing - sorry I am new to swift. thanks to everybody tried to help
Whole working Code:
import UIKit
import ELCImagePickerController
class ViewController: UIViewController, UINavigationControllerDelegate, ELCImagePickerControllerDelegate {
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.
}
var picker = ELCImagePickerController()
#IBAction func OpenPhotos(_ sender: AnyObject) {
picker.imagePickerDelegate = self
self.present(picker, animated: true, completion: nil)
}
func elcImagePickerController(_ picker: ELCImagePickerController!, didFinishPickingMediaWithInfo info: [Any]!) {
dismiss(animated: true, completion: nil)
}
func elcImagePickerControllerDidCancel(_ picker: ELCImagePickerController!) {
dismiss(animated: true, completion: nil)
}
}
I'm trying to make the camera pop up on a button click, but my view is not persisting because I keep getting an error:
Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates.
I have an imageView rendered to place the picture when after it's shot, using the ImagePickerController function, but I'm guessing it's somehow not being pushed to the view.
Do you have any ideas?
Code that might be helpful is below:
- Basically, ViewController creates a UIView capturebutton, and when it is tapped, a Camera view controller is presented.
ViewController
class ViewController: UIViewController, UIScrollViewDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate{
let rect1 = CGRectMake(100, 60, 40, 60)
let captureButton2 = UIView(frame: rect1)
captureButton2.backgroundColor = UIColor.blueColor()
captureButton2.addGestureRecognizer(UITapGestureRecognizer(target: self, action: Selector("didTapImageView:")))
scrollView.addSubview(captureButton2)
func didTapImageView(tap: UITapGestureRecognizer){
let captureDetails = storyboard!.instantiateViewControllerWithIdentifier
("CameraVC")! as? CameraVC3
presentViewController(captureDetails!, animated: true, completion: nil)
}
CameraViewController
class CameraVC3: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIViewControllerTransitioningDelegate{
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera){
var imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.Camera;
imagePicker.mediaTypes = [kUTTypeImage]
imagePicker.allowsEditing = false
self.presentViewController(imagePicker, animated: true, completion: nil)
}
}
var photoImageView2 = UIImageView(frame: CGRectMake(40, 120, 200, 200))
// handles output
func ImagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!){
photoImageView2.image = image
picker.dismissViewControllerAnimated(true, completion: nil)
}
Got it! I needed to add a line in my viewDidLoad() fn
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(photoImageView)
}