Press ESC to close

SwiftUI Camera & Gallery

Merhaba arkadaşlar, bu yazıda SwiftUI ile nasıl fotoğraf çekilir ve galeriden fotoğraf seçilir gibi konulara bakacağız. Hemen hemen bir çok projede kullandığımız bu işlemler için şu anda SwiftUI tarafında bir kontrol bulunmuyor. Bu yüzden UIKit ile bu işlemi gerçekleştirmemiz gerekiyor. UIKit’ten bir elemen kullanmak istediğimizde ise UIViewControllerRepresentable protokolünü kullanmamız gerekiyor.

İlk önce basit bir ekran tasarımı yapalım. Yukarıda 2 adet buton olan bir tasarım olacak. Bunlardan birisi kameradan fotoğraf çekmek için diğeri ise galeriden fotoğraf seçmek için. Bu butonların altında ise kameradan veya galeriden gelen fotoğraf yer alacak.

Bu ekranda 3 farklı State tanımlıyoruz. Bu statelerden birisi fotoğraf çekmek ve galeriden fotoğraf seçmek için açılan sayfanın açılıp açılmadığı. Bunun isImagePickerPresenting State’i ile tutuyoruz. Diğeri seçilen veya çekilen fotoğrafı tutmak için en son ise kameradan fotoğraf çekme mi yoksa galeriden fotoğraf seçme seçeneği olacak. Sonrasında ise basit bir tasarım ekledik.

//
//  ContentView.swift
//  swiftui_camera_gallery
//
//  Created by Omer Sezer on 27.12.2020.
//

import SwiftUI

struct ContentView: View {
    @State var isImagePickerPresenting: Bool = false
    @State var selectedPhoto: UIImage?
    @State var sourceType: UIImagePickerController.SourceType = .photoLibrary
    
    var body: some View {
        VStack {
            HStack {
                if UIImagePickerController.isSourceTypeAvailable(.camera) {
                    Button(action: {
                        sourceType = .camera
                        isImagePickerPresenting = true
                    }, label: {
                        Text("Camera")
                            .foregroundColor(.black)
                    })
                    Spacer()
                }
                
                Button(action: {
                    sourceType = .photoLibrary
                    isImagePickerPresenting = true
                }, label: {
                    Text("Gallery")
                        .foregroundColor(.black)
                })
            }
            .padding()
            Spacer()
            if let selectedPhoto = selectedPhoto {
                Image(uiImage: selectedPhoto)
                    .resizable()
            }
        }
        .sheet(isPresented: $isImagePickerPresenting, content: {
            ImagePicker(sourceType: sourceType, selectedPhoto: $selectedPhoto)
        })
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

UIViewControllerRepresentable

Asıl önemli işlem ise UIKit tarafından bir kontrol oluşturup buna SwiftUI ile haberleştirmek. Bunun için bir ImagePicker kontrolü oluşturuyorum. Bu yapı 2 adet değişken alacak. Bunlardan birisi fotoğraf mı yoksa galerinin mi açılacağı. Diğeri ise alınan veya çekilen fotoğrafı SwiftUI’a transferi için oluşturulan değişkeni. UIViewControllerRepresentable protokolü 2 adet fonksiyon istiyor. Bunlardan makeUIViewController fonksiyonu, UIKit’den kontrol oluşturmak için. Diğeri ise o kontrolü update etmek için. Benim için burada sadece kontrolü oluşturmak yeterli. Sonrasında bunun delegate’ini bağlamak için bir coordinator oluşturuyorum. Bu coordinator ile fotoğraf çekme veya seçme işlemi bittikten sonra selectedPhoto değişkenine atıyorum.

//
//  ImagePicker.swift
//  swiftui_camera_gallery
//
//  Created by Omer Sezer on 27.12.2020.
//

import UIKit
import SwiftUI

struct ImagePicker {
    var sourceType: UIImagePickerController.SourceType = .photoLibrary
    @Binding var selectedPhoto: UIImage?
}

extension ImagePicker: UIViewControllerRepresentable {
    
    func makeUIViewController(context: Context) -> some UIViewController {
        let imagePicker = UIImagePickerController()
        imagePicker.allowsEditing = true
        imagePicker.sourceType = sourceType
        imagePicker.delegate = context.coordinator
        return imagePicker
    }
    
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        
    }
    
    func makeCoordinator() -> ImagePickerCoordinater {
        ImagePickerCoordinater(self)
    }
}

class ImagePickerCoordinater: NSObject  {
    var imagePicker: ImagePicker
    
    init(_ picker: ImagePicker) {
        self.imagePicker = picker
        super.init()
    }
}

extension ImagePickerCoordinater: UIImagePickerControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let selectedPhoto = info[.editedImage] as? UIImage ?? info[.originalImage] as? UIImage {
            imagePicker.selectedPhoto = selectedPhoto
        } else {
            imagePicker.selectedPhoto = nil
        }
        
        picker.dismiss(animated: true, completion: nil)
    }
}

extension ImagePickerCoordinater: UINavigationControllerDelegate { }

Projeye buradan ulaşabilirsiniz.Sorularınız olursa mail veya yorum atarak ulaşabilirsiniz. İyi çalışmalar.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir