下記のサイトのコードを打ち込んで、動画撮影のアプリを作ろうとしています。
質問したいことは2つあります。
1.@objcとは、objetive-cのことでしょうか?下記のコードはswiftではないですか?
2.storyboardと紐付けする場合、@IBOutlet、@IBActionのコードが生成されると思うのですが、下記のコードはそれがありません。紐付け前ということでしょうか?
環境 xcode11.4 swift4.2です。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
ベストアンサー
1.@objcとは、objetive-cのことでしょうか?下記のコードはswiftではないですか?
現在、Swift/SwiftUI をベースとした環境での開発が中心となりつつありますが、やはり従前使われてきた Objective-C の資産も使わざるを得ない場面がでてきます。
そのことをコンパイラに伝えるための一種のキーワードだと思ってください(おそらく、それ以上深く考える必要は今はないかと思います)。
2.storyboardと紐付けする場合、@IBOutlet、@IBActionのコードが生成されると思うのですが、下記のコードはそれがありません。紐付け前ということでしょうか?
いいえ、ご提示いただいているサンプルコードは、StoryBoard に部品を配置することなく実行できるよう作成されたコードです。
なので紐付けは一切必要ありません。
しかし、StoryBoard は一切使わないのかというとそういう訳でもなく、初期(Initial)ページとなる View Controller を一つ配置しておく必要はあります。
簡単に手順を示すと、
- 通常の Swift/StoryBoard を作る手順でプロジェクトを新規作成する
- StoryBoard には一切手を加えない
- ViewController.swift にサンプルのコードをそのままコピー&ペーストする
- Info.plist を編集する
- 「実機で」実行する
というステップで実行できると思います。
##2020年10月1日追記
参考にされたコードは iOS10 以降ではそのまま使えないため、使えるように一部変更を加えてみました。
また、オリジナルのコードはだと、録画終了後指定したフォルダに映像を保存するだけで、実はビデオライブラリには保存されないため、録画状態を確認することができません(要は、「写真」アプリで録画された映像を確認することができない)。
また、UIの一部が少し紛らわしいため、その修正も加えたコードを下記に提示しますので、コード中のコメントをよく読まれた上、試してみていただけますでしょうか。
Swift
1// This code is originally based on http://faboplatform.github.io/SwiftDocs/5.avfoundation/003_avfoundation/ 2// Some lines of this program are modified to enable to run this code correctly after iOS 10.0 ,and added codes to save captured image to the Photo library. 3 4import UIKit 5import AVFoundation 6 7// MARK: - フォトライブラリに保存するために必要 8import Photos 9 10class ViewController: UIViewController, AVCaptureFileOutputRecordingDelegate { 11 12 // ビデオのアウトプット. 13 private var myVideoOutput: AVCaptureMovieFileOutput! 14 15 // スタートボタン. 16 private var myButtonStart: UIButton! 17 18 // ストップボタン. 19 private var myButtonStop: UIButton! 20 21 override func viewDidLoad() { 22 super.viewDidLoad() 23 print(#function) 24 // セッションの作成. 25 let mySession = AVCaptureSession() 26 27 // デバイス. 28 var myDevice = AVCaptureDevice.default(for: .video) 29 30 // 出力先を生成. 31 // let myImageOutput = AVCaptureStillImageOutput() 32 // MARK: - 'AVCaptureStillImageOutput' was deprecated in iOS 10.0: Use AVCapturePhotoOutput instead. 33 // 警告通り、AVCapturePhotoOutput() でインスタンスを生成するよういする 34 let myImageOutput = AVCapturePhotoOutput() 35 36 // デバイス一覧の取得. 37 // let devices = AVCaptureDevice.devices() 38 // MARK: - 'devices()' was deprecated in iOS 10.0: Use AVCaptureDeviceDiscoverySession instead. 39 // 警告に従うが、警告で出力されているメソッド名が微妙に異なる(AVCaptureDevice.DiscoverySessionが正解)なので注意する 40 // 詳しい使い方は公式ドキュメントを参照 41 // refer to: https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/choosing_a_capture_device 42 let devices = AVCaptureDevice.DiscoverySession(deviceTypes: 43 [.builtInTrueDepthCamera, .builtInDualCamera, .builtInWideAngleCamera], 44 mediaType: .video, position: .unspecified).devices 45 // マイクを取得. 46 let audioCaptureDevice = AVCaptureDevice.default(for: .audio) 47 48 // マイクをセッションのInputに追加. 49 let audioInput = try! AVCaptureDeviceInput.init(device: audioCaptureDevice!) 50 51 // バックライトをmyDeviceに格納. 52 53 // for device in devices { 54 // if(device.position == AVCaptureDevice.Position.back){ 55 // myDevice = device 56 // } 57 // } 58 // MARK: - オリジナルのコードから一部変更。 59 guard !devices.isEmpty else { fatalError("選択されたデバイスは存在しません") } 60 myDevice = devices.first { $0.position == .back } 61 62 // バックカメラを取得. 63 let videoInput = try! AVCaptureDeviceInput.init(device: myDevice!) 64 65 // ビデオをセッションのInputに追加. 66 mySession.addInput(videoInput) 67 68 // オーディオをセッションに追加. 69 mySession.addInput(audioInput) 70 71 // セッションに追加. 72 mySession.addOutput(myImageOutput) 73 74 // 動画の保存. 75 myVideoOutput = AVCaptureMovieFileOutput() 76 77 // ビデオ出力をOutputに追加. 78 mySession.addOutput(myVideoOutput) 79 80 // 画像を表示するレイヤーを生成. 81 let myVideoLayer = AVCaptureVideoPreviewLayer.init(session: mySession) 82 myVideoLayer.frame = self.view.bounds 83 // myVideoLayer.session = myDevice 84 myVideoLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill 85 86 // Viewに追加. 87 self.view.layer.addSublayer(myVideoLayer) 88 89 // セッション開始. 90 mySession.startRunning() 91 92 // UIボタンを作成. 93 myButtonStart = UIButton(frame: CGRect(x: 0, y: 0, width: 120, height: 50)) 94 myButtonStop = UIButton(frame: CGRect(x: 0, y: 0, width: 120, height: 50)) 95 96 myButtonStart.backgroundColor = UIColor.red 97 myButtonStop.backgroundColor = UIColor.gray 98 99 myButtonStart.layer.masksToBounds = true 100 myButtonStop.layer.masksToBounds = true 101 102 myButtonStart.setTitle("撮影", for: .normal) 103 myButtonStop.setTitle("停止", for: .normal) 104 105 myButtonStart.layer.cornerRadius = 20.0 106 myButtonStop.layer.cornerRadius = 20.0 107 108 myButtonStart.layer.position = CGPoint(x: self.view.bounds.width/2 - 70, y:self.view.bounds.height-50) 109 myButtonStop.layer.position = CGPoint(x: self.view.bounds.width/2 + 70, y:self.view.bounds.height-50) 110 111 myButtonStart.addTarget(self, action: #selector(ViewController.onClickMyButton), for: .touchUpInside) 112 myButtonStop.addTarget(self, action: #selector(ViewController.onClickMyButton), for: .touchUpInside) 113 114 // UIボタンをViewに追加. 115 self.view.addSubview(myButtonStart) 116 self.view.addSubview(myButtonStop) 117 118 // 119 myButtonStop.isHidden = true 120 } 121 122 // MARK: 123 func toggleButtonStatus() { 124 // 125 myButtonStop.isHidden.toggle() 126 myButtonStart.isHidden.toggle() 127 } 128 129 /* 130 ボタンイベント. 131 */ 132 @objc internal func onClickMyButton(sender: UIButton){ 133 // 撮影開始. 134 if( sender == myButtonStart ){ 135 // MARK: 136 toggleButtonStatus() 137 138 let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) 139 140 // フォルダ. 141 let documentsDirectory = paths[0] 142 143 // ファイル名. 144 let filePath = "(documentsDirectory)/test.mp4" 145 146 // URL. 147 let fileURL = URL(fileURLWithPath: filePath) 148 149 // 録画開始. 150 myVideoOutput.startRecording(to: fileURL, recordingDelegate: self) 151 152 } 153 // 撮影停止. 154 else if ( sender == myButtonStop ){ 155 // 156 toggleButtonStatus() 157 158 myVideoOutput.stopRecording() 159 } 160 } 161 162 // MARK: - AVCaptureFileOutputRecordingDelegate 163 164 /* 165 動画がキャプチャーされた後に呼ばれるメソッド. 166 */ 167 func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) { 168 print("didFinishRecordingTo outputFileURL") 169 170 // MARK: - フォトライブラリにビデオを保存するのであれば、以下のコードを追加した上、NSPhotoLibraryAddUsageDescription を Info.plist に追加する必要がある。 171 PHPhotoLibrary.shared().performChanges({ 172 PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: outputFileURL) 173 }) { completed, error in 174 if completed { 175 print("Video is saved!") 176 } 177 } 178 } 179 180 /* 181 動画のキャプチャーが開始された時に呼ばれるメソッド. 182 */ 183 func fileOutput(_ output: AVCaptureFileOutput, didStartRecordingTo fileURL: URL, from connections: [AVCaptureConnection]) { 184 print("didStartRecordingTo fileURL") 185 } 186}
投稿2020/10/01 01:25
編集2020/10/01 13:52総合スコア5086
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2020/10/01 06:21
2020/10/01 13:48