今回作るもの
今回はアプリ内で写真を撮影したり自身のフォトライブラリから写真を取り込んだりする機能を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に使用内容を書きましょう

以上で終わりです。
画像の保存については今後説明できればと思います。
コメント