본문 바로가기
iOS/이슈

[iOS Issue] CustomView에서 sublayer 추가 시 이슈

by Sky Titan 2021. 6. 4.
728x90

 카메라 프리뷰를 보여주는 Custom View를 만들던 중 AVCaptureVideoPreviewLayer를 superView frame에 맞춰서 sublayer로 넣었으나 superView의 크기 계산이 sublayer를 추가하고 난 이후에 이루어져서 계속 크기가 틀어짐

 

 그래서 기존 custom View의 Main layer 클래스를 AVCaptureVideoPreviewLayer 로 바꾸어서 해결

//
//  CameraView.swift
//  MyFoundation
//
//

import UIKit
import AVFoundation

open class CameraView: UIView  {
    private lazy var captureDevice = AVCaptureDevice.default(for: .video)
    private var session: AVCaptureSession?
    private var output = AVCapturePhotoOutput()
    
    private var captureCompletion: ((UIImage) -> Void)?
    
    public var isRunning: Bool {
        return session?.isRunning ?? false
    }
    
    //change Main Layer Class
    public override class var layerClass: Swift.AnyClass {
        return AVCaptureVideoPreviewLayer.self
    }
    
    private var previewLayer: AVCaptureVideoPreviewLayer? {
        return layer as? AVCaptureVideoPreviewLayer
    }
    
    public override init(frame: CGRect) {
        super.init(frame: frame)
        setUp()
    }
    
    public required init?(coder: NSCoder) {
        super.init(coder: coder)
        setUp()
    }
    
    deinit {
        captureCompletion = nil
    }
    
    private func setUp() {
        settingCamera()
        startRunning()
    }
    
    private func settingCamera() {
        guard let captureDevice = captureDevice else { return }
        do {
            let input = try AVCaptureDeviceInput(device: captureDevice)
            session = AVCaptureSession()
            session?.sessionPreset = .photo
            session?.addInput(input)
            session?.addOutput(output)
            
        } catch {
            print(error)
        }
        clipsToBounds = true
        guard let session = session else { return }
        previewLayer?.session = session
        previewLayer?.videoGravity = .resize //비율 해제
    }
    
    public func startRunning() {
        session?.startRunning()
    }
    
    public func stopRunning() {
        session?.stopRunning()
    }
    
    public func capture(completion: ((UIImage) -> Void)?) {
        captureCompletion = completion
        output.capturePhoto(with: .init(), delegate: self)
    }
}

extension CameraView: AVCapturePhotoCaptureDelegate {
    
    //MARK: - 셔터 소리 나기 전 호출
    public func photoOutput(_ output: AVCapturePhotoOutput, willBeginCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings) {
        
    }
    
    //MARK: - 셔터 소리 직후 호출 (깜빡거리는 효과, 플래시 적용, 찍은 사진 호출)
    public func photoOutput(_ output: AVCapturePhotoOutput, willCapturePhotoFor resolvedSettings: AVCaptureResolvedPhotoSettings) {
        
    }
    
    //MARK: - 캡쳐 후 이미지를 data로 받기
    public func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        guard let data = photo.fileDataRepresentation(), let image = UIImage(data: data) else {return}
        
        captureCompletion?(image)
    }
    
    //MARK: - 모든 동작 끝나면 호출
    public func photoOutput(_ output: AVCapturePhotoOutput, didFinishCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings, error: Error?) {
        
    }
}
728x90

댓글