如何在 iOS8.1 上使用 Swift 按顺序拍摄多张照片(每张延迟 1 秒)?

Posted

技术标签:

【中文标题】如何在 iOS8.1 上使用 Swift 按顺序拍摄多张照片(每张延迟 1 秒)?【英文标题】:How to take multiple photos in a sequence (1s delay each), using Swift on iOS8.1? 【发布时间】:2014-10-29 22:02:14 【问题描述】:

我正在尝试在单个用户单击相机预览后拍摄几张照片,以便我可以展示它们,并且用户可以选择时间最佳的一张或在“胶片条”模式下使用所有照片。预期的用户体验是:“我打开相机,拍照,然后我看到 5 张照片一秒一秒地拍摄。我不必按 5 次‘拍照’按钮,一张就足以启动序列” .

我是 ios 和 Swift 的新手,我的工作基于一本“Swift 食谱”一书 (https://www.safaribooksonline.com/library/view/ios-8-swift/9781491908969/)。

单张拍照源码为:

controller = UIImagePickerController()
    if let theController = controller
        theController.sourceType = .Camera
        theController.mediaTypes = [kUTTypeImage as NSString]
        theController.allowsEditing = true
        theController.delegate = self
        presentViewController(theController, animated: true, completion: nil)
    

加上相关的图像处理(通过 func imagePickerController)。我尝试使用上面的控制器对象,但失败了:(我相信这不是获得我想要的东西的正确方法,但我很难找到正确的方法。任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

我不知道UIImagePickerController 中是否有这种行为的模式。如果我是你,我会使用 AVFoundation 来实现它。

import UIKit
import AVFoundation

class ViewController: UIViewController 

    var connection: AVCaptureConnection!
    var output: AVCaptureStillImageOutput!
    var videoPreviewLayer: AVCaptureVideoPreviewLayer!
    @IBOutlet var videPreviewView: UIView!

    override func viewDidLoad() 
        super.viewDidLoad()

        self.createCamera()
    

    override func viewDidLayoutSubviews() 
        super.viewDidLayoutSubviews()

        self.videoPreviewLayer.bounds = self.videPreviewView.bounds
        self.videoPreviewLayer.position = CGPoint(x: CGRectGetMidX(self.videPreviewView.bounds), y: CGRectGetMidY(self.videPreviewView.bounds))
    

    func createCamera() 
        let captureSession = AVCaptureSession()

        if captureSession.canSetSessionPreset(AVCaptureSessionPresetHigh) 
            captureSession.sessionPreset = AVCaptureSessionPresetHigh
         else 
            println("Error: Couldn't set preset = \(AVCaptureSessionPresetHigh)")
            return
        

        let cameraDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)

        var error: NSError?
        let inputDevice = AVCaptureDeviceInput.deviceInputWithDevice(cameraDevice, error: &error) as AVCaptureDeviceInput
        if let error = error 
            println("Error: \(error)")
            return
        

        if captureSession.canAddInput(inputDevice) 
            captureSession.addInput(inputDevice)
         else 
            println("Error: Couldn't add input device")
            return
        

        let imageOutput = AVCaptureStillImageOutput()
        if captureSession.canAddOutput(imageOutput) 
            captureSession.addOutput(imageOutput)
         else 
            println("Error: Couldn't add output")
            return
        

        // Store imageOutput. We will need it to take photo
        self.output = imageOutput

        let connection = imageOutput.connections.first as AVCaptureConnection!
        // Store this connection in property. We will need it when we take image.
        self.connection = connection
        connection.videoOrientation = AVCaptureVideoOrientation.Portrait

        captureSession.startRunning()

        // This will preview the camera
        let videoLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        videoLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
        videoLayer.contentsScale = UIScreen.mainScreen().scale

        self.videPreviewView.layer.addSublayer(videoLayer)

        // Store this layer instance in property. We will place it into a view
        self.videoPreviewLayer = videoLayer
    

    func takePhoto(completion: (UIImage?, NSError?) -> Void) 
        self.output.captureStillImageAsynchronouslyFromConnection(self.connection)  buffer, error in
            if let error = error 
                completion(nil, error)
             else 
                let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(buffer)
                let image = UIImage(data: imageData, scale: UIScreen.mainScreen().scale)
                completion(image, nil)
            
        
    

现在您所要做的就是创建一个调用takePhoto 3 次的操作。您可以使用NSTimer 来执行此操作。

【讨论】:

如何用 UIButton 调用 takePhoto?

以上是关于如何在 iOS8.1 上使用 Swift 按顺序拍摄多张照片(每张延迟 1 秒)?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Swift 按字母顺序将表格视图数据划分为多个部分? (重写)

如何在 AppDelegate.swift 中按常规顺序调用 ViewController

ViewDidLoad 未按正确顺序执行操作 - Firebase、Swift

Swift按顺序绘制多个圆圈

Swift 按顺序执行异步任务

如何按顺序执行任务?斯威夫特3