뷰에서 버튼을 누르면 이미지 피커를 띄우고 이미지 피커에서 선택된 이미지가 저장되도록 한다.
Utilities 폴더에 아래의 ImagePicker 코드를 추가한다. 이 코드를 간략하게 설명하자면, ImagePicker를 보여주고 사용자가 하나의 이미지를 선택하면 바인딩된 image 상태값에 해당 이미지를 저장하고 화면이 닫힌다.
import SwiftUI
struct ImagePicker: UIViewControllerRepresentable {
@Binding var image: UIImage?
@Environment(\.presentationMode) var mode
func makeUIViewController(context: Context) -> some UIViewController {
let picker = UIImagePickerController()
picker.delegate = context.coordinator
return picker
}
func makeCoordinator() -> Coordinator {
return Coordinator(self)
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
}
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
let parent: ImagePicker
init(_ parent: ImagePicker) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let image = info[.originalImage] as? UIImage else { return }
self.parent.image = image
self.parent.mode.wrappedValue.dismiss()
}
}
}
@State private var imagePickerPresented = false
@State private var selectedImage: UIImage?
@State private var profileImage: Image?
플러스 버튼을 누르면 imagePicker를 띄우고 싶다. 이 버튼의 action에서 imagePickerPresented 토글을 추가한다.
imagePickerPresented.toggle()
버튼의 label은 프로필 이미지가 없으면 plus 이미지를, 있으면 프로필 이미지를 보여준다.
Button(action: {
imagePickerPresented.toggle()
}, label: {
let image = profileImage == nil ? Image(systemName: "plus.circle") : channelImage ?? Image(systemName: "plus.circle")
image
.resizable()
.scaledToFill()
.frame(width: 64, height: 64)
.clipShape(Circle())
})
Apple Developer Documentation - sheet(isPresented:onDismiss:content:)
Presents a sheet when a binding to a Boolean value that you provide is true.
제공한 바인딩된 불린값이 true일 경우 sheet를 보여준다.
버튼 코드의 뒤에 sheet를 연결한다.
.sheet(isPresented: $imagePickerPresented,
onDismiss: loadImage,
content: { ImagePicker(image: $selectedImage) })
onDismiss 함수에는 loadImage 함수를 넣는다. selectedImage가 UIImage타입이므로 Image 타입으로 변환해 profileImage에 저장하는 함수이다.
func loadImage() {
guard let selectedImage = selectedImage else { return }
profileImage = Image(uiImage: selectedImage)
}