在Swift 2 iOS中访问相机

时间:2015-09-22 17:38:48

标签: ios swift swift2 xcode7 avcapturesession

我正在尝试访问相机并在我的iPad应用程序中拍照,下面是适用于swift 1.2的代码,但在Swift 2中有3种类型的错误(在BLOCK注释中突出显示)失败。我花时间寻找快速2写作方式,但没有得到任何地方。任何建议都受到高度赞赏。

import UIKit
import AVFoundation

class PictureController: UIViewController {

    let captureSession = AVCaptureSession()
    var previewLayer : AVCaptureVideoPreviewLayer?

    // If we find a device we'll store it here for later use
    var captureDevice : AVCaptureDevice?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view, typically from a nib.
        captureSession.sessionPreset = AVCaptureSessionPresetHigh

        let devices = AVCaptureDevice.devices()

        // Loop through all the capture devices on this phone
        for device in devices {
            // Make sure this particular device supports video
            if (device.hasMediaType(AVMediaTypeVideo)) {
                // Finally check the position and confirm we've got the back camera
                if(device.position == AVCaptureDevicePosition.Back) {
                    captureDevice = device as? AVCaptureDevice
                    if captureDevice != nil {
                        print("Capture device found")
                        beginSession()
                    }
                }
            }
        }

    }

    func focusTo(value : Float) {
        if let device = captureDevice {
            if(device.lockForConfiguration(nil)) { // CALL CAN THROW BUT IS NOT MARKED WITH 'TRY' AND THE ERROR IS NOT HANDLED
// nil IS NOT COMPATIBLE WITH EXPECTED ARGUMENT TYPE '()'
                device.setFocusModeLockedWithLensPosition(value, completionHandler: { (time) -> Void in
                    //
                })
                device.unlockForConfiguration()
            }
        }
    }

    let screenWidth = UIScreen.mainScreen().bounds.size.width
    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { //METHOD DOES NOT OVERRIDE ANY METHOD FROM SUPERCLASS
        let anyTouch = touches.anyObject() as! UITouch
        let touchPercent = anyTouch.locationInView(self.view).x / screenWidth
        focusTo(Float(touchPercent))
    }

    override func touchesMoved(touches: NSSet, withEvent event: UIEvent) { //METHOD DOES NOT OVERRIDE ANY METHOD FROM SUPERCLASS
        let anyTouch = touches.anyObject() as! UITouch
        let touchPercent = anyTouch.locationInView(self.view).x / screenWidth
        focusTo(Float(touchPercent))
    }

    func configureDevice() {
        if let device = captureDevice {
            device.lockForConfiguration(nil) // CALL CAN THROW BUT IS NOT MARKED WITH 'TRY' AND THE ERROR IS NOT HANDLED
// nil IS NOT COMPATIBLE WITH EXPECTED ARGUMENT TYPE '()'
            device.focusMode = .Locked
            device.unlockForConfiguration()
        }

    }

    func beginSession() {

        configureDevice()

        var err : NSError? = nil
        captureSession.addInput(AVCaptureDeviceInput(device: captureDevice, error: &err)) 
// Cannot invoke initializer for type 'AVCaptureDeviceInput' with an argument list of type '(device: AVCaptureDevice?, error: inout NSError?)'

        if err != nil {
            print("error: \(err?.localizedDescription)")
        }

        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        self.view.layer.addSublayer(previewLayer)
        previewLayer?.frame = self.view.layer.frame
        captureSession.startRunning()
    }


}

错误1:调用可以抛出,但没有标记为'try'并且未处理错误 类型'()'不符合协议'BooleanType'

错误2:方法不会覆盖其超类中的任何方法 for touchesBegan和touchesMoved

错误3:无法使用类型为'(device:AVCaptureDevice?,error:inout NSError?)的参数列表调用类型'AVCaptureDeviceInput'的初始值设定项。

更新:

所有其他问题都已修复(如果您正在寻找解决方案,请参考评论),除了以下一项。

func focusTo(value : Float) {
        if let device = captureDevice {
            if(device.lockForConfiguration()) { // THIS LINE IS THROWING BELOW MENTIONED ERROR
                device.setFocusModeLockedWithLensPosition(value, completionHandler: { (time) -> Void in

                })
                device.unlockForConfiguration()
            }
        }
    }

ERROR:

  

类型'()'不符合协议'BooleanType'

     

调用可以抛出,但没有标记为'try'并且未处理错误

2 个答案:

答案 0 :(得分:4)

do {
    try device.lockForConfiguration()
    device.setFocusModeLockedWithLensPosition(value, completionHandler: { (time) -> Void in
                //
    })
    device.unlockForConfiguration()
} catch let error as NSError {
    print(error.code)
}


override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

}

答案 1 :(得分:1)

我在这里为Swift2发布了一个完整的解决方案,其中包含了来自gkhanacer https://stackoverflow.com/a/36719940/2144994的解决方案以及此问题中的所有代码示例。这是一个完整的ViewController

import UIKit
import AVFoundation

class FirstViewController: UIViewController {

let captureSession = AVCaptureSession()
var previewLayer : AVCaptureVideoPreviewLayer?

// If we find a device we'll store it here for later use
var captureDevice : AVCaptureDevice?

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view, typically from a nib.
    captureSession.sessionPreset = AVCaptureSessionPresetHigh

    let devices = AVCaptureDevice.devices()

    // Loop through all the capture devices on this phone
    for device in devices {
        // Make sure this particular device supports video
        if (device.hasMediaType(AVMediaTypeVideo)) {
            // Finally check the position and confirm we've got the back camera
            if(device.position == AVCaptureDevicePosition.Back) {
                captureDevice = device as? AVCaptureDevice
                if captureDevice != nil {
                    print("Capture device found")
                    beginSession()
                }
            }
        }
    }

}

let screenWidth = UIScreen.mainScreen().bounds.size.width

func configureDevice() {
    if let device = captureDevice {
        do {
        try device.lockForConfiguration()
        device.focusMode = .AutoFocus
        device.unlockForConfiguration()
        } catch let error as NSError {
            print(error.code)
        }
    }

}


override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

    let screenSize = previewLayer!.bounds.size
    let frameSize:CGSize = view.frame.size
    if let touchPoint = touches.first {

        let location:CGPoint = touchPoint.locationInView(self.view)

        let x = location.x / frameSize.width
        let y = 1.0 - (location.x / frameSize.width)

        let focusPoint = CGPoint(x: x, y: y)

        print("POINT : X: \(x), Y: \(y)")


        let captureDevice = (AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) as! [AVCaptureDevice]).filter{$0.position == .Back}.first

        if let device = captureDevice {
            do {
                try device.lockForConfiguration()

                let support:Bool = device.focusPointOfInterestSupported

                if support  {

                    print("focusPointOfInterestSupported: \(support)")

                    device.focusPointOfInterest = focusPoint

                    // device.focusMode = .ContinuousAutoFocus
                    device.focusMode = .AutoFocus
                    // device.focusMode = .Locked

                    device.unlockForConfiguration()

                    print("Focus point was set successfully")
                }
                else{
                    print("focusPointOfInterestSupported is not supported: \(support)")
                }
            }
            catch {
                // just ignore
                print("Focus point error")
            }
        }
    }
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {

    if let touch = touches.first{
        print("\(touch)")
    }
    super.touchesEnded(touches, withEvent: event)
}

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {

    if let touch = touches.first{
        print("\(touch)")
    }
    super.touchesMoved(touches, withEvent: event)
}


func beginSession() {

    configureDevice()

    try! captureSession.addInput(AVCaptureDeviceInput(device: captureDevice))
    // Cannot invoke initializer for type 'AVCaptureDeviceInput' with an argument list of type '(device: AVCaptureDevice?, error: inout NSError?)'


    previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    self.view.layer.addSublayer(previewLayer!)
    previewLayer?.frame = self.view.layer.frame
    captureSession.startRunning()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}