سؤال

My requirement is to write a sample IOS app that would automatically capture a camera picture. Using the various S.O links provided I did implement the below code -

My CameraViewController.h class is defined as follows :

@interface CameraViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>

@property (strong, nonatomic) IBOutlet UIImageView *ImageView;

@end

And CameraViewController.m has the below code :

    -(void)viewDidAppear:(BOOL)animated
{
    NSLog(@"Setting the background now");

    UIImagePickerController *picker = [[UIImagePickerController alloc] init];picker.delegate = self;
    picker.allowsEditing = YES;
    picker.sourceType = UIImagePickerControllerSourceTypeCamera;
    picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
    picker.cameraDevice = UIImagePickerControllerCameraDeviceRear;
    picker.showsCameraControls = NO;
    picker.navigationBarHidden = NO;
    picker.toolbarHidden = NO;
    [self presentViewController:picker animated:YES completion:NULL];

    NSLog(@"Taking the picture now");
   [picker takePicture];


}


-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

{
    NSLog(@"Entered the case of finishing pictures");
}

- (void) imagePickerControllerDidCancel: (UIImagePickerController *) picker
{
    NSLog(@"Entered the case of cancel");

}

What the above code does is successfully launch the camera app , however I am not sure if the takePicture API is able to successfully click a picture . I do not see any saved pictures in the Photos app inside my Ipad so I assume that the picture has not been clicked . Can someone please tell me if my code above is correct or what do I need to do to automate the part of clicking the capture button once the Camera controls are displayed

هل كانت مفيدة؟

المحلول

[Please go to 'Using UIImagePickerController to Select Pictures and Take Photos' in the Apple documentation for the property cameraOverlayView of class UIImagePickerController for a complete example application that does what you need, and more.]

You specified your CameraViewController as adopting the UIImagePickerControllerDelegate protocol and thus you must implement two messages:

- (void)   imagePickerController: (UIImagePickerController *) picker      
   didFinishPickingMediaWithInfo: (NSDictionary *) info;

and

- (void) imagePickerControllerDidCancel: (UIImagePickerController *) picker;

As the iOS documentation describes, the NSDictionary* info has a key UIImagePickerControllerOriginalImage which will return the UIImage. Access it as something like:

UIImage *snapshot = (UIImage *) [info objectForKey: UIImagePickerControllerOriginalImage];

Since your plan is to take a picture automatically (w/o user interaction) using takePicture then be sure to specify

  picker.showsCameraControls = NO;

نصائح أخرى

You need to implement the UIImagePIckerControllerDelegate's imagePickerController:didFinishPickingMediaWithInfo: method.

After that, look inside the mediaInfo dictionary and there's a UIImage inside it you can use.

I know this is old, but a better alternative to using a timer (see the comments from the accepted answer) would be to implement the completion handler instead of passing in NULL.

[self presentViewController:picker animated:YES completion:^{
    NSLog(@"Taking the picture now");
    [picker takePicture];
}];

That way, the picture is taken consistently every time, and you don't waste time adding an unnecessary delay.

**You can auto capturing both camera image and video recording by use this code.**

import UIKit
import AVFoundation
import MobileCoreServices

class ViewController: UIViewController, UIGestureRecognizerDelegate {

    let captureSession = AVCaptureSession()
    var captureDevice : AVCaptureDevice?
    var imagePicker = UIImagePickerController()
    var flagVideoRecording = false
    var arrImages = [UIImage]()
    var countVideoRecording = 0
    var labelTime = UILabel()
    var timer: Timer?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(actionRepeatCapturing), name: .AVCaptureSessionDidStartRunning, object: nil)
    }
    
    @objc func actionRepeatCapturing() {
        flagVideoRecording = false
        startCapturingBothImageAndRecordView()
    }
    
    //MARK:- UIButton's Action
    @IBAction func actionCaptureImage(_ sender: UIButton) {
        flagVideoRecording = false
        
        if AVCaptureDevice.authorizationStatus(for: AVMediaType.video) ==  AVAuthorizationStatus.authorized {
            startCapturingBothImageAndRecordView()
        } else {
            AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler: { (granted: Bool) -> Void in
                if granted == true {
                    self.startCapturingBothImageAndRecordView()
                } else {
                    DispatchQueue.main.async {
                        self.alertToEncourageAccessInitially("Camera access required for capturing photos!", actionTitle: "Allow Camera")
                    }
                }
            })
        }
    }
    
    @IBAction func actionCaptureVideo(_ sender: UIButton) {
        flagVideoRecording = true
        if AVCaptureDevice.authorizationStatus(for: AVMediaType.video) ==  AVAuthorizationStatus.authorized {
            switch AVAudioSession.sharedInstance().recordPermission {
            case AVAudioSession.RecordPermission.granted:
                self.startCapturingBothImageAndRecordView()
            case AVAudioSession.RecordPermission.denied:
                self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
            case AVAudioSession.RecordPermission.undetermined:
                
                AVAudioSession.sharedInstance().requestRecordPermission({ (granted) in
                    if granted {
                        self.startCapturingBothImageAndRecordView()
                    } else {
                        self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
                    }
                })
                
            default:
                break
            }
        } else {
            AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler: { (granted: Bool) -> Void in
                if granted == true {
                    switch AVAudioSession.sharedInstance().recordPermission {
                    case AVAudioSession.RecordPermission.granted:
                        self.startCapturingBothImageAndRecordView()
                    case AVAudioSession.RecordPermission.denied:
                        self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
                    case AVAudioSession.RecordPermission.undetermined:
                        
                        AVAudioSession.sharedInstance().requestRecordPermission({ (granted) in
                            if granted {
                                self.startCapturingBothImageAndRecordView()
                            } else {
                                self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
                            }
                        })
                        
                    default:
                        break
                    }
                } else {
                    DispatchQueue.main.async {
                        self.alertToEncourageAccessInitially("Camera access required for record video", actionTitle: "Allow Camera")
                    }
                }
            })
        }
    }
}

extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    func startCapturingBothImageAndRecordView() {
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera) {
            debugPrint("captureVideoPressed and camera available.")
            imagePicker = UIImagePickerController()
            imagePicker.delegate = self
            imagePicker.sourceType = .camera
            if flagVideoRecording {
                imagePicker.mediaTypes = [kUTTypeMovie as String]
                imagePicker.allowsEditing = false
                imagePicker.showsCameraControls = false
                
                let viewTime = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 40))
                viewTime.backgroundColor = .black
                viewTime.alpha = 0.1
                labelTime = UILabel(frame: CGRect(x: self.view.frame.width/2-50, y: 10, width: 100, height: 25))
                labelTime.font = UIFont.boldSystemFont(ofSize: 17)
                labelTime.text = "00.00:00"
                labelTime.textColor = .white
                labelTime.textAlignment = .center
                labelTime.backgroundColor = .red
                imagePicker.view.addSubview(viewTime)
                imagePicker.view.addSubview(labelTime)
                
                self.timer = Timer.scheduledTimer(timeInterval: 1,
                                     target: self,
                                     selector: #selector(self.actionStopVideoRecording),
                                     userInfo: nil,
                                     repeats: true)
            } else {
                imagePicker.allowsEditing = false
                imagePicker.showsCameraControls = false
            }
        } else {
            debugPrint("Camera not available.")
        }
        
        
        self.present(self.imagePicker, animated: true, completion: {
            if self.flagVideoRecording {
                self.imagePicker.startVideoCapture()
            } else {
                self.imagePicker.takePicture()
            }
        })
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        
        if flagVideoRecording {
            if let videoFileURL = info[UIImagePickerController.InfoKey.mediaURL] as? URL {
                debugPrint(videoFileURL)
                
//                let data = try Data(contentsOf: videoFileURL, options: .mappedIfSafe)
//                debugPrint(data)
            }
            self.dismiss(animated: true, completion: nil)
        } else {
            if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage{
                arrImages.append(pickedImage)
            }
            
            sleep(1)
            
            if arrImages.count >= 5 {
                self.dismiss(animated: true, completion: nil)
            } else {
                NotificationCenter.default.post(name: .AVCaptureSessionDidStartRunning, object: nil, userInfo: nil)
            }
        }
    }
    
    @objc func actionStopVideoRecording() {
        countVideoRecording += 1
        labelTime.text = countVideoRecording == 10 ? "00:00:\(countVideoRecording)":"00:00:0\(countVideoRecording)"
        
        if countVideoRecording == 10 {
            imagePicker.stopVideoCapture()
            timer?.invalidate()
            timer = nil
        }
    }
}

extension ViewController {
    func alertToEncourageAccessInitially(_ msgString: String, actionTitle: String) {
        let alert = UIAlertController(
            title: "IMPORTANT",
            message: msgString,
            preferredStyle: UIAlertController.Style.alert
        )
        alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
        alert.addAction(UIAlertAction(title: actionTitle, style: .destructive, handler: { (alert) -> Void in
            let myUrl = URL(string: UIApplication.openSettingsURLString)!
                if let url = URL(string: "\(myUrl)"), !url.absoluteString.isEmpty {
                    UIApplication.shared.open(url, options: [:], completionHandler: nil)
                }

                // or outside scope use this
                guard let url = URL(string: "\(myUrl)"), !url.absoluteString.isEmpty else {
                   return
                }
                 UIApplication.shared.open(url, options: [:], completionHandler: nil)
        }))
        present(alert, animated: true, completion: nil)
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top