skip to Main Content

I want to put a camera preview in the first collectionCell (like Telegram does) (while other cells is filled with photos from gallery). And when user tap on the first cell, i need to show a camera. However i’ve got a crash without any info in xCode when i’m tapping the cell.

let cameraPicker: UIImagePickerController = {
    let picker = UIImagePickerController()
    picker.sourceType = .camera
    picker.cameraDevice = .front
    picker.showsCameraControls = false
    return picker
}()
override func viewDidLoad() {
    super.viewDidLoad()
    imageCollectionView.delegate = self
    imageCollectionView.dataSource = self
    if UIImagePickerController.isCameraDeviceAvailable(.front) {
        cameraPicker.delegate = self
        //my cell size
        let screenSize = CGSize(width: 80, height: 80)
        let cameraAspectRatio = CGFloat(4.0 / 3.0)
        let cameraImageHeight = screenSize.width * cameraAspectRatio
        let scale = screenSize.height / 40
        cameraPicker.cameraViewTransform = CGAffineTransform(translationX: 0, y: (screenSize.height - cameraImageHeight)/2)
        cameraPicker.cameraViewTransform = cameraPicker.cameraViewTransform.scaledBy(x: scale, y: scale)
    
        cameraPicker.view.frame = CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height)
    }

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    guard let cell = cell as? PSTBaseImageCollectionViewCell else { return  }
    cell.imageView.subviews.forEach{$0.removeFromSuperview()}
    cell.imageView.image = nil
    if indexPath.row == 0 {
        
    } else {
        let asset = allPhotos?.object(at: indexPath.row - 1)
        cell.imageView.fetchImageFromAsset(asset: asset!, contentMode: .aspectFill, targetSize: CGSize(width: asset!.pixelWidth, height: asset!.pixelHeight))
    }
}
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    if indexPath.row == 0 {
        if UIImagePickerController.isSourceTypeAvailable(.camera) {
            cameraPicker.showsCameraControls = true
            present(cameraPicker, animated: true)
        }
    }
}

In this case, if i tap on the first cell, camera presented normally, but when i add a camera preview in the cell, camera view doesn’t present anymore

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    guard let cell = cell as? PSTBaseImageCollectionViewCell else { return  }
    cell.imageView.subviews.forEach{$0.removeFromSuperview()}
    cell.imageView.image = nil
    if indexPath.row == 0 {
        cell.imageView.addSubview(cameraPicker.view)
    } else {
        let asset = allPhotos?.object(at: indexPath.row - 1)
        cell.imageView.fetchImageFromAsset(asset: asset!, contentMode: .aspectFill, targetSize: CGSize(width: asset!.pixelWidth, height: asset!.pixelHeight))
    }
}

What am i missing?

2

Answers


  1. Why are you using willDisplay to setup your cell?

    https://developer.apple.com/documentation/uikit/uicollectionviewdelegate/1618087-collectionview?language=objc

    “ Discussion
    The collection view calls this method before adding a cell to its content. Use this method to detect cell additions, as opposed to monitoring the cell itself to see when it appears.”

    Use this: https://developer.apple.com/documentation/uikit/uicollectionviewdatasource/1618029-collectionview

    Login or Signup to reply.
  2. I’m probably too late for this, but I found a solution.
    I did the same thing in my app, but instead of an imageview, I added a UIView and turned its isUserInteractionEnabled to false

    In cellForRowAt:

    if indexPath.row == 0 {
        cell.preview.addSubview(cameraPicker.view)
        cameraPicker.view.frame = cell.imageView.bounds
        cell.preview.isUserInteractionEnabled = false
    } else {
        let asset = allPhotos?.object(at: indexPath.row - 1)
        cell.imageView.fetchImageFromAsset(asset: asset!, contentMode: .aspectFill, targetSize: CGSize(width: asset!.pixelWidth, height: asset!.pixelHeight))
    }
    

    I still have an imageView in the cell, but thats just to show a gradient tint with my apps logo (alpha set to 0.3) so that it looks like an overlay

    EDIT: I also realized you never set a frame for the camera preview

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search