6
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SwiftUI(macOS)でAVPlayerViewを使う

Posted at

macOSアプリのSwiftUIで動画を再生するAVPlayerViewを使いたい場合は、NSViewRepresentableに適合するViewを自分で用意する必要がある。

import SwiftUI
import AVKit

struct PlayerView: NSViewRepresentable {
    @Binding var player: AVPlayer
    
    func updateNSView(_ NSView: NSView, context: NSViewRepresentableContext<PlayerView>) {
        guard let view = NSView as? AVPlayerView else {
            debugPrint("unexpected view")
            return
        }
        
        view.player = player
    }
    
    func makeNSView(context: Context) -> NSView {
        return AVPlayerView(frame: .zero)
    }
}

makeNSViewAVPlayerViewの実体を作った後、updateNSView内でplayerをセットする。

struct ContentView: View {
    @ObservedObject var videoItem: VideoItem = VideoItem()
    
    var body: some View {
        VStack {
            if videoItem.playerItem != nil {
                PlayerView(player: $videoItem.player)
            }
            Button(action: {
                let panel = NSOpenPanel()
                panel.allowedFileTypes = [kUTTypeMovie as String]
                DispatchQueue.main.async {
                    if panel.runModal() == .OK {
                        guard let url = panel.url else {
                            return
                        }
                        self.videoItem.open(url)
                    }
                }
            }) {
                Text("Open")
            }
        }.frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

View側では、playerをBindする。

ファイルを読み直した際に、複数のAVPlayerが生成されることを防ぐため、AVPlayer自体は一つのインスタンスを使い回し、replaceCurrentItemplayerItemを切り替えていく形で実装するとシンプルになる。

import SwiftUI
import AVFoundation

class VideoItem: ObservableObject {
    @Published var player: AVPlayer = AVPlayer()
    @Published var playerItem: AVPlayerItem?
    
    func open(_ url: URL) {
        let asset = AVAsset(url: url)
        let playerItem = AVPlayerItem(asset: asset)
        self.playerItem = playerItem
        player.replaceCurrentItem(with: playerItem)
    }
}
6
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?