質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.39%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

3130閲覧

【swift4】カメラで撮った写真をフォルダに保存する

maplesugar_17

総合スコア32

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2020/06/16 13:13

編集2020/06/17 02:08

こんばんは。swiftUIを使用してシンプルなカメラアプリを開発しています。
シャッターボタンを押した時に写真を取り、それを写真フォルダに保存したいです。

swift

1import Foundation 2import AVFoundation 3import UIKit 4import Combine 5 6class CameraController: NSObject{ 7 8 // デバイスからの入力と出力を管理するオブジェクトの作成 9 var captureSession = AVCaptureSession() 10 11 // カメラの画質の設定 12 func setupCaptureSession() { 13 captureSession.sessionPreset = AVCaptureSession.Preset.photo 14 } 15 16 // カメラデバイスそのものを管理するオブジェクトの作成 17 // メインカメラの管理オブジェクトの作成 18 var mainCamera: AVCaptureDevice? 19 // インカメの管理オブジェクトの作成 20 var innerCamera: AVCaptureDevice? 21 // 現在使用しているカメラデバイスの管理オブジェクトの作成 22 var currentDevice: AVCaptureDevice? 23 24 // デバイスの設定 25 func setupDevice() { 26 // カメラデバイスのプロパティ設定 27 let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera], mediaType: AVMediaType.video, position: AVCaptureDevice.Position.unspecified) 28 // プロパティの条件を満たしたカメラデバイスの取得 29 let devices = deviceDiscoverySession.devices 30 31 for device in devices { 32 if device.position == AVCaptureDevice.Position.back { 33 mainCamera = device 34 } else if device.position == AVCaptureDevice.Position.front { 35 innerCamera = device 36 } 37 } 38 // 起動時のカメラを設定 39 currentDevice = mainCamera 40 } 41 42 43 // キャプチャーの出力データを受け付けるオブジェクト 44 var photoOutput = AVCapturePhotoOutput() 45 46 // 入出力データの設定 47 func setupInputOutput() { 48 do { 49 // 指定したデバイスを使用するために入力を初期化 50 let captureDeviceInput = try AVCaptureDeviceInput(device: currentDevice!) 51 // 指定した入力をセッションに追加 52 captureSession.addInput(captureDeviceInput) 53 // 出力データを受け取るオブジェクトの作成 54 photoOutput = AVCapturePhotoOutput() 55 // 出力ファイルのフォーマットを指定 56 photoOutput.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format: [AVVideoCodecKey : AVVideoCodecType.jpeg])], completionHandler: nil) 57 captureSession.addOutput(photoOutput) 58 } catch { 59 print(error) 60 } 61 } 62 63 // プレビュー表示用のレイヤ 64 var cameraPreviewLayer : AVCaptureVideoPreviewLayer? 65 66 // カメラのプレビューを表示するレイヤの設定 67 func setupPreviewLayer() { 68 // 指定したAVCaptureSessionでプレビューレイヤを初期化 69 self.cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession) 70 // プレビューレイヤが、カメラのキャプチャーを縦横比を維持した状態で、表示するように設定 71 self.cameraPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill 72 // プレビューレイヤの表示の向きを設定 73 self.cameraPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.portrait 74 } 75 76 override init() { 77 super.init() 78 setupCaptureSession() 79 setupDevice() 80 setupInputOutput() 81 setupPreviewLayer() 82 captureSession.startRunning() 83 } 84 85 func cameraButton_TouchUpInside(_ sender: Any) { 86 let settings = AVCapturePhotoSettings() 87 // フラッシュの設定 88 89 settings.flashMode = .auto 90 // 撮影された画像をdelegateメソッドで処理 91 self.photoOutput.capturePhoto(with: settings, delegate: self as AVCapturePhotoCaptureDelegate) 92 } 93} 94 95extension CameraController: AVCapturePhotoCaptureDelegate{ 96 func photoOutput(_ output: AVCapturePhotoOutput, 97 didFinishProcessingPhoto photo: AVCapturePhoto, 98 error: Error?){ 99 if let imageData = photo.fileDataRepresentation() { 100 // Data型をUIImageオブジェクトに変換 101 let uiImage = UIImage(data: imageData) 102 // 写真ライブラリに画像を保存 103 UIImageWriteToSavedPhotosAlbum(uiImage!, nil,nil,nil) 104 } 105 } 106} 107

こちらが実際のカメラの設定ファイルです。

ContentViewで、

swift

1Button(action: { 2 //シャッター 3 CameraController().cameraButton_TouchUpInside(self) 4 print("Round Action") 5}) { 6 Circle() 7 .fill(Color.black) 8 .frame(width: UIScreen.screenWidth/6, height: UIScreen.screenWidth/6) 9 .shadow(radius: 10) 10}

を呼んでいます。 しかし、cameraButton_TouchUpInside(self)は呼ばれているのですが、photoOutputは呼ばれていませんでした。
お手隙の際に何を修正すればいいのかご教示くだされば幸いです。

回答者さまにご指摘いただきましたが、不勉強故に出典のリンクを貼るのを忘れていました。申し訳ありません。
今回参考にさせていただきました記事:
Swiftでカメラアプリを作成する(1)
Swiftでカメラアプリを作成する(2)

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

photoOutput が呼ばれない理由は、CameraController オブジェクトが作ったその場で破棄されてしまい、photoOutput が呼ばれるタイミングでは存在しなくなってるからで、とりあえずプロパティに持たせておけば呼ばれるようになります。

diff

1 struct ContentView: View { 2+ private var cameraController = CameraController() 3 4 var body: some View { 5 Button(action: { 6 //シャッター 7- CameraController().cameraButton_TouchUpInside(self) 8+ self.cameraController.cameraButton_TouchUpInside(self) 9 print("Round Action") 10 }) { 11 // 以下略

なお、元記事 (これですよね? 出典は明記しましょう。)

では UIKit (UIViewController) を使ってプレビューの表示なども行ってますが、SwiftUI でそれをやるには UIViewControllerRepresentable ってやつを使う必要があるようです。
参考: How to show a AVCaptureVideoPreviewLayer in SwiftUI - Stack Overflow
参考: https://github.com/owingst/SwiftUIScanner

投稿2020/06/17 00:30

hoshi-takanori

総合スコア7899

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maplesugar_17

2020/06/17 02:07

ありがとうございました、無事解決いたしました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.39%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問