2

I am trying to access camera and take a picture in my iPad app, below is the code which works for swift 1.2 but is failing with 3 types of errors(highlighted below in BLOCK comments) in Swift 2. I have spent time looking for swift 2 way of writing it but haven't gotten anywhere. Any suggestion is highly appreciated.

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()
    }
    
    
}

error 1: Call can throw, but it is not marked with 'try' and the error is not handled Type '()' does not conform to protocol 'BooleanType'

error 2: Method does not override any method from its superclass for touchesBegan and touchesMoved

error 3: Cannot invoke initializer for type 'AVCaptureDeviceInput' with an argument list of type '(device: AVCaptureDevice?, error: inout NSError?)'

UPDATE:

ALL OTHER ISSUES ARE FIXED (please ref comments if you are looking for solutions), EXCEPT FOR THE BELOW ONE.

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:

Type '()' does not conform to protocol 'BooleanType'

Call can throw, but it is not marked with 'try' and the error is not handled

Community
  • 1
  • 1
Nagendra Rao
  • 7,016
  • 5
  • 54
  • 92

2 Answers2

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?) {

}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • Works, now I am trying to figure out this error `Method does not override any method from its superclass` for touchesBegan and touchesMoved – Nagendra Rao Sep 22 '15 at 18:15
  • Did that, now its throwing `Method 'touchesBegan(_:withEvent:)' with Objective-C selector 'touchesBegan:withEvent:' conflicts with method 'touchesBegan(_:withEvent:)' from superclass 'UIResponder' with the same Objective-C selector` – Nagendra Rao Sep 22 '15 at 18:17
  • You just need to let it autocomplete when typing it. Take a look at my edit. This error has been asked already many times. – Leo Dabus Sep 22 '15 at 18:17
  • Did that, `func touchesBegan(touches: Set, withEvent event: UIEvent?) { let touchPercent = touches.locationInView(self.view).x / screenWidth focusTo(Float(touchPercent)) }` Now this throws `Value of type 'Set' has no member 'locationInView'` – Nagendra Rao Sep 22 '15 at 18:22
  • Thanks! Now I have no errors but the view is white-blank page in my simulator. Do you know of any tutorial which demos how to use camera in Swift 2.0 ? – Nagendra Rao Sep 22 '15 at 18:36
  • Simulator doesn't simulate a camera – Leo Dabus Sep 22 '15 at 18:37
  • Let me check on an actual iPad. Thanks for your help, really appreciate it. – Nagendra Rao Sep 22 '15 at 18:40
1

I am posting a complete solution here for Swift2, which incorporates solutions from gkhanacer https://stackoverflow.com/a/36719940/2144994 and all the code examples in this question. This is a complete 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.
}


}
Community
  • 1
  • 1
user43633
  • 319
  • 3
  • 7