UIView constraints causing issues

I have a camera app that uses a uiview to take the photo. When not using constraints the uiview fills its area only leaving a small amount of background color on the left and right sides. However when I put constraints on the uiview and run it on my iPad this happens as you can see the uiveiw is not using all of the area.

          import UIKit
       import AVFoundation

     class ViewController: UIViewController,AVCapturePhotoCaptureDelegate  {

     var captureSesssion : AVCaptureSession!
       var cameraOutput : AVCapturePhotoOutput!
    var previewLayer : AVCaptureVideoPreviewLayer!

    @IBOutlet weak var capturedImage: UIImageView!
    @IBOutlet weak var previewView: UIView!

    override func viewDidLoad() {
     super.viewDidLoad()

captureSesssion = AVCaptureSession()
captureSesssion.sessionPreset = AVCaptureSessionPresetPhoto
cameraOutput = AVCapturePhotoOutput()

let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)

if let input = try? AVCaptureDeviceInput(device: device) {
    if (captureSesssion.canAddInput(input)) {
        captureSesssion.addInput(input)
        if (captureSesssion.canAddOutput(cameraOutput)) {
            captureSesssion.addOutput(cameraOutput)
            previewLayer = AVCaptureVideoPreviewLayer(session: captureSesssion)
            previewLayer.frame = previewView.bounds
            previewView.layer.addSublayer(previewLayer)




            captureSesssion.startRunning()
        }
    } else {
        print("issue here : captureSesssion.canAddInput")
    }
    } else {
    print("some problem here")
    }
      }


     @IBAction func didPressTakePhoto(_ sender: UIButton) {
   let settings = AVCapturePhotoSettings()
  let previewPixelType = settings.availablePreviewPhotoPixelFormatTypes.first!
    let previewFormat = [
    kCVPixelBufferPixelFormatTypeKey as String: previewPixelType,
    kCVPixelBufferWidthKey as String: 160,
    kCVPixelBufferHeightKey as String: 160
 ]
 settings.previewPhotoFormat = previewFormat
 cameraOutput.capturePhoto(with: settings, delegate: self)




}



 func capture(_ captureOutput: AVCapturePhotoOutput,  didFinishProcessingPhotoSampleBuffer photoSampleBuffer: CMSampleBuffer?,  previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings:  AVCaptureResolvedPhotoSettings, bracketSettings:   AVCaptureBracketedStillImageSettings?, error: Error?) {

    if let error = error {
        print("error occure : \(error.localizedDescription)")
    }

    if  let sampleBuffer = photoSampleBuffer,
        let previewBuffer = previewPhotoSampleBuffer,
        let dataImage =     AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer:  sampleBuffer, previewPhotoSampleBuffer: previewBuffer) {
        print(UIImage(data: dataImage)?.size as Any)

        let dataProvider = CGDataProvider(data: dataImage as CFData)
        let cgImageRef: CGImage! = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: .defaultIntent)
        let image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: UIImageOrientation.right)


        self.capturedImage.image = image


        UIImageWriteToSavedPhotosAlbum(image, self, #selector(self.image(_:didFinishSavingWithError:contextInfo:)), nil)
    } else {
        print("some error here")
    }
}


func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
    if let error = error {
        // we got back an error!
        let ac = UIAlertController(title: "Save error", message: error.localizedDescription, preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "OK", style: .default))
        present(ac, animated: true)
    } else {
        let ac = UIAlertController(title: "Image Saved!", message: "Your image has been saved to your photos.", preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "OK", style: .default))
        present(ac, animated: true)
    }
}
 func askPermission() {
print("here")
let cameraPermissionStatus =  AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)

switch cameraPermissionStatus {
case .authorized:
    print("Already Authorized")
case .denied:
    print("denied")

    let alert = UIAlertController(title: "Sorry :(" , message: "But  could you please grant permission for camera within device settings",  preferredStyle: .alert)
    let action = UIAlertAction(title: "Ok", style: .cancel,  handler: nil)
    alert.addAction(action)
    present(alert, animated: true, completion: nil)

case .restricted:
    print("restricted")
default:
    AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: {
        [weak self]
        (granted :Bool) -> Void in

        if granted == true {
            // User granted
            print("User granted")
            DispatchQueue.main.async(){
                //Do smth that you need in main thread   
            } 
        }
        else {
            // User Rejected
            print("User Rejected")

            DispatchQueue.main.async(){
                let alert = UIAlertController(title: "WHY?" , message:  "Camera it is the main feature of our application", preferredStyle: .alert)
                let action = UIAlertAction(title: "Ok", style: .cancel, handler: nil)
                alert.addAction(action)
                self?.present(alert, animated: true, completion: nil)  
            } 
        }
    });
}}}

I don’t see any constraint samples so let me be general. When I add a view as a contained view (and this is one of the most common ways I do things) I do something very much like:

    toolbarViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ToolbarViewController") as? ToolbarViewController

    addChildViewController(toolbarViewController!)
    toolbarContainerView.addSubview(toolbarViewController!.view)
    toolbarViewController!.didMove(toParentViewController: self)
    toolbarView = toolbarViewController!.view!
    
    toolbarView?.translatesAutoresizingMaskIntoConstraints = false
    
    let leftConstraint = NSLayoutConstraint(item: toolbarView!, attribute: .left, relatedBy: .equal, toItem: toolbarContainerView, attribute: .left, multiplier: 1.0, constant: 0.0)
    let rightConstraint = NSLayoutConstraint(item: toolbarView!, attribute: .right, relatedBy: .equal, toItem: toolbarContainerView, attribute: .right, multiplier: 1.0, constant: 0.0)
    let topConstraint = NSLayoutConstraint(item: toolbarView!, attribute: .top, relatedBy: .equal, toItem: toolbarContainerView, attribute: .top, multiplier: 1.0, constant: 0.0)
    let bottomConstraint = NSLayoutConstraint(item: toolbarView!, attribute: .bottom, relatedBy: .equal, toItem: toolbarContainerView, attribute: .bottom, multiplier: 1.0, constant: 0.0)
    toolbarContainerView.addConstraints([leftConstraint, rightConstraint, topConstraint, bottomConstraint])

And that will fill a container view that you create in a view controller with a view that is created as the main view of a view controller instantiated through the storyboard.

The main thing to realise about constraints is that they must all be satisfied simultaneously. Typically you must leave something undefined (in absolute terms) - so if a collection of child views form a certain width, then to allow resizing at least one of those views must not have an absolute size assigned but be defined by its proximity to other views on left and right.

What you have going on there I am not sure, but you could see what the existing constraints are with a tool like Reveal. I think you might have constraints on the added (photo) view, and those are keeping it at that size. I think if you remove those constraints and use a series of constraints as shown above it will fill the green view.

1 Like

in what function do I put the code in?

Typically you use the view when you need it. I’m not sure you need to be using layers there. When the photo view is ready why not just change the image of a view you have already added as a contained view? You could do this in viewDidLoad and then it is there all the time, only you display the image in that view when it is available.

I am just a little confused with toolbarViewController only one view controller contains all of the function need to shot the image. That view controller is just called the default viewController. Would I replace toolbarViewController with ViewController? Thanks.

toolbarViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ToolbarViewController") as? ToolbarViewController