SwiftUI에서 PHPhotoPicker 사용

이 기사는 무엇입니까?



PHPhotoPicker를 SwiftUI에서 사용하는 앱을 만듭니다.



실행 환경



Swift 5.3
Xcode 12.5
macOS 11.3

Photos 프레임워크



"장치에 저장된 사진"을 얻기위한 개인 정보 보호를 고려한 완전히 새로운 프레임 워크입니다.

핸즈온



순서를 따라 앱을 만들겠습니다.

기본 화면



기본 화면에는 '사진을 표시하기 위한 프레임'과 '사진 선택기를 열기 위한 버튼'을 배치합니다.
우선, 「사진을 표시하는 테두리」의 뷰를 작성해 둡니다.

PhotoFrame.swift
import SwiftUI

struct PhotoFrame: View {
    @Binding var image: Image?

    var body: some View {
        if let image = image {
            image
                .resizable()
                .aspectRatio(contentMode: .fit)
        } else {
            Image(systemName: "photo")
                .font(.title)
                .foregroundColor(.gray)
        }
    }
}

그런 다음 '사진 선택기 열기 버튼'을 만듭니다.

ShowPickerButton.swift
import SwiftUI

struct ShowPickerButton: View {
    @Binding var isShowLibrary: Bool

    var body: some View {
        Button(action: {
            isShowLibrary = true
        }, label: {
            Text("Choose Photo")
                .font(.title2)
                .padding()
                .background(Color.blue)
                .foregroundColor(.white)
                .cornerRadius(10.0)
        })
    }
}

이 보기를 기본 화면에 배치합니다.

ContentView.swift
import SwiftUI

struct ContentView: View {
    @State private var isShowPhotoLibrary = false
    @State var image: Image?
    @EnvironmentObject var classifier: ImageClassifier

    var body: some View {
        ZStack {
            PhotoFrame(image: $image)
            VStack {
                Spacer()
                Text(classifier.classificationLabel)
                ShowPickerButton(isShowLibrary: $isShowPhotoLibrary)
            }
        }
        .sheet(isPresented: $isShowPhotoLibrary, content: {
            PhotoPicker(isPresented: $isShowPhotoLibrary,
                        seledtedImage: $image)
        })
    }
}

사진 선택기의 보기 만들기



UIKit의 뷰 컨트롤러를 SwiftUI에서 사용하려면 ViewControllerRepresentable 프로토콜에 적합한 구조로 래핑합니다.

PhotoPicker.swift
import SwiftUI
import PhotosUI

struct PhotoPicker: UIViewControllerRepresentable {
    @Binding var isPresented: Bool
    @Binding var seledtedImage: Image?

    func makeUIViewController(context: Context) -> PHPickerViewController {
        var configuration = PHPickerConfiguration()
        configuration.filter = .images

        let picker = PHPickerViewController(configuration: configuration)
        picker.delegate = context.coordinator

        return picker
    }

    func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {
        // do nothing.
    }
}

PhotoPicker 유형 정의



대리자 메서드를 통해 PhotoPickerViewController와 상호작용하려면 중개자인 Coordinator 클래스를 정의해야 합니다.

PhotoPicker.swift


코디네이터 정의



이 클래스는 PhotoPicker 구조체의 중첩 형식으로 정의합니다.

코디네이터 클래스
import SwiftUI
import PhotosUI

struct PhotoPicker: UIViewControllerRepresentable {
    @Binding var isPresented: Bool
    @Binding var seledtedImage: Image?

    func makeUIViewController(context: Context) -> PHPickerViewController {...}

    func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {
        // do nothing.
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: PHPickerViewControllerDelegate {
        private let parent: PhotoPicker

        init(_ parent: PhotoPicker) {
            self.parent = parent
        }

        func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
            parent.isPresented = false

            let itemProvider = results.first?.itemProvider  // itemProvider is NSItemProvider? Type.

            if let itemProvider = itemProvider, itemProvider.canLoadObject(ofClass: UIImage.self) {
                itemProvider.loadObject(ofClass: UIImage.self) { (image, error) in
                    if let uiImage = image as? UIImage {
                        self.parent.seledtedImage = Image(uiImage: uiImage)
                    }
                }
            }
        }
    }
}

마지막으로



WWDC2021에서 PHPickerView가 SwiftUI 네이티브가되면 좋겠다.

좋은 웹페이지 즐겨찾기