Search code examples
iosswiftipadcamera

Swift Playground iPad cameras access


In the last update notes for the Swift Playground app for the iPad I saw that the cameras would be accessible through the playgrounds. For testing purpose I've therefore created a playground to access my iPads back camera. As reference I've used those sources:

Here is my code:

import UIKit
import AVFoundation
import PlaygroundSupport

class MainViewController : UIViewController {
    private var _session: AVCaptureSession?
    private var _captureInput: AVCaptureInput?
    private var _stillImageOutput: AVCaptureStillImageOutput?
    private var _frontCamera: AVCaptureDevice?
    private var _previewView: UIView?
    private var _previewLayer: AVCaptureVideoPreviewLayer?

public override func loadView() {
    print("loadView()")

    _previewView = UIView()
    guard let view = _previewView else {
        printError(errMsg: "View could not be created!")
        return
    }
    view.backgroundColor = UIColor.brown
    self.view = view
}

public override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    // Create a capture session
    _session = AVCaptureSession()
    guard let session = _session  else {
        printError(errMsg: "Session is empty!")
        return
    }
    session.beginConfiguration()
    session.sessionPreset = AVCaptureSession.Preset.photo

    // Get access to front camera
    _frontCamera = AVCaptureDevice.default(for: AVMediaType.video)

    guard let frontCamera = _frontCamera
        else {
            printError(errMsg: "Front camera not accessible!")
            return
    }

    do{
        _captureInput = try AVCaptureDeviceInput(device: frontCamera)
    } catch let err as NSError {
        printError(errMsg: err.localizedDescription)
        return
    }

    // Add input to session
    guard let captureInput = _captureInput else {
        printError(errMsg: "Capture input not available!")
        return
    }

    if session.canAddInput(captureInput){
        session.addInput(captureInput)
    }

    // Configurw the image output
    _stillImageOutput = AVCaptureStillImageOutput()
    guard let sillImageOutput = _stillImageOutput else {
        printError(errMsg: "Image output not available!")
        return
    }

    sillImageOutput.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]

    if session.canAddOutput(sillImageOutput) {
        session.addOutput(sillImageOutput)
    }
    session.commitConfiguration()
    // Add video preview layer
    _previewLayer = AVCaptureVideoPreviewLayer(session: session)

    guard let previewLayer = _previewLayer else {
        printError(errMsg: "Preview layer not available!")
        return
    }

    previewLayer.videoGravity = AVLayerVideoGravity.resizeAspect
    previewLayer.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
    guard let view = _previewView else {
        printError(errMsg: "View not available!")
        return
    }
    view.layer.addSublayer(previewLayer)
    view.layer.borderWidth = 5

    // Start the capture session
    session.startRunning()
}

public override func viewDidLoad() {
    super.viewDidLoad()
}

public override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    guard let previewLayer = _previewLayer else {
        printError(errMsg: "Preview layer not available!")
        return
    }
    guard let previewView = _previewView else {
        printError(errMsg: "View not available!")
        return
    }
    print(previewView.bounds)
    previewLayer.frame = previewView.bounds
}

private func printError(errMsg: String) {
    print("[Error]: " + errMsg)
}
}

PlaygroundPage.current.liveView = MainViewController()

Please ignore the private variables for the session, etc. I know that I can/should make them method local.

The only thing I see is the brown background of the view. enter image description here When running the app for the first time iOS asked me if the Playgrounds app should have access to the camera which I accepted. In the settings I can also see that the app has access to the camera.

iOS Version: 10.3.3 Playground App: 1.6.1


Solution

  • It looks like it works only on iOS 11. I checked your code on iPad with iOS 10.3 and the video preview was empty. The same code was running just fine inside the normal app. On another tablet running iOS 11 the same code was working like a charm.