swiftUIでカメラ撮影機能とフォトライブラリ選択を実装

SWIFTUI

今回作るもの

今回はアプリ内で写真を撮影したり自身のフォトライブラリから写真を取り込んだりする機能をswiftUIでつくっていきたいと思います。

実装手順

ImagePicker.swiftファイルを作成

ImagePicker.swiftを新たに作成し、以下の内容を記入。

(コピペで大丈夫です!)

import Foundation
import SwiftUI

struct ImagePicker: UIViewControllerRepresentable {
    
    @Environment(\\.presentationMode) var presentationMode
    @Binding var imageselected: UIImage
    @Binding var sourceType: UIImagePickerController.SourceType
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController{
        let picker = UIImagePickerController()
        picker.delegate = context.coordinator
        picker.sourceType = sourceType
        picker.allowsEditing = true
        return picker
    }
    
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: UIViewControllerRepresentableContext<ImagePicker>) {}
    
    func makeCoordinator() -> ImagePickerCoordinator {
        return ImagePickerCoordinator(parent: self)
    }
    
    class ImagePickerCoordinator: NSObject,UINavigationControllerDelegate, UIImagePickerControllerDelegate{
        
        let parent: ImagePicker
        
        init(parent: ImagePicker){
            self.parent = parent
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]){
            if let image = info[.editedImage] as? UIImage ?? info[.originalImage] as? UIImage {
                // select the image for our app
                parent.imageselected = image
                // dismiss the screen
                parent.presentationMode.wrappedValue.dismiss()
                
            }
        }
    }
}

ここで書かれている内容は今回は省略しますが、Bindingされている2つについて説明すると、

  • imageselected = 選択された画像
  • sourceType = カメラモードかフォトライブラリを読み込むか

となります。

ActionSheetを使ってImagePickerを呼び出す(ContentView)

次に、先程のImagePickerを呼び出す部分を作っていきたいと思います。

// UIKitをインポート
import UIKit
import SwiftUI

struct ContentView: View {
    @State var showAlert: Bool = false
    @State var showImagePicker: Bool = false
    @State var imageSelected: UIImage = UIImage(named: "logo")! //デフォルトの画像を最初にいれておく
    @State var sourceType: UIImagePickerController.SourceType = .camera
    
    @State var showPostImageView: Bool = false
    
    var body: some View {

         // 略

                Button(action: {
                    showAlert.toggle()
                }, label: {
                    Image(systemName: "plus.circle.fill")
                        .font(.system(size: 50))
                        .foregroundColor(.gray)
                })
                .padding(.bottom, 70)
                .padding(.trailing,40)
                .actionSheet(isPresented: $showAlert) {
                    ActionSheet(title: Text("Upload New Photo"), message: nil, buttons: [
                        .default(Text("Take Photo"),action:{. //カメラモード
                            sourceType = UIImagePickerController.SourceType.camera
                            showImagePicker.toggle()
                        }),
                        .default(Text("Import Photo"),action:{  // フォトライブラリモード
                            sourceType = UIImagePickerController.SourceType.photoLibrary
                            showImagePicker.toggle()
                        }),
                        .cancel(). // キャンセル
                    ])
                }
                .sheet(isPresented: $showImagePicker, onDismiss: segueToPostImageView) {
                                         // ImagePickerを呼び出す
                    ImagePicker(imageselected: $imageSelected, sourceType: $sourceType)
                }
            }

PostImageViewで、ImagePickerで作成した画像を次の画面に表示

今度はImagePickerから呼び出す画面を作ります。

struct PostImageView: View {
    @Environment(\.presentationMode) var presentationMode
    @Binding var imageSelected: UIImage
    
    var body: some View {
        VStack(alignment: .center, spacing: 0, content: {
            HStack {
                Button(action: {
                    //画面を閉じる
                    presentationMode.wrappedValue.dismiss()
                }, label: {
                    Image(systemName: "xmark")
                        .font(.title)
                        .padding()
                })
                .accentColor(.primary)
                Spacer()
            }
                                //選択された画像を表示
                Image(uiImage: imageSelected)
                    .resizable()
                    .scaledToFill()
                    .frame(maxWidth:.infinity, maxHeight: 300)
                    .clipped()

PostImageViewをフルスクリーンで呼び出す

もう一度ContentViewに戻って以下を追記


 struct ContentView: View {
    @State var showAlert: Bool = false
    @State var showImagePicker: Bool = false
    @State var imageSelected: UIImage = UIImage(named: "logo")!
    @State var sourceType: UIImagePickerController.SourceType = .camera
    
    @State var showPostImageView: Bool = false
    
    var body: some View {
                                   // 略
                 .actionSheet(isPresented: $showAlert) {
                    ActionSheet(title: Text("Upload New Photo"), message: nil, buttons: [
                        .default(Text("Take Photo"),action:{
                            sourceType = UIImagePickerController.SourceType.camera
                            showImagePicker.toggle()
                        }),
                        .default(Text("Import Photo"),action:{
                            sourceType = UIImagePickerController.SourceType.photoLibrary
                            showImagePicker.toggle()
                        }),
                        .cancel()
                    ])
                }
                .sheet(isPresented: $showImagePicker, onDismiss: segueToPostImageView) {
                    ImagePicker(imageselected: $imageSelected, sourceType: $sourceType)
                }
            }

            //こちらを追加
            .fullScreenCover(isPresented: $showPostImageView, content: {
                PostImageView(imageSelected: $imageSelected)
            })

これで実装完了です。あとはinfo.plistファイルにカメラ使用のプライバシーを書いていきましょう

info.plistに使用内容を書きましょう

以上で終わりです。

画像の保存については今後説明できればと思います。

コメント

タイトルとURLをコピーしました