[Swift4/Cocoa] 動画をAVPlayerViewにドラッグ&ドロップで読み込む

2018年6月21日(更新: 2018年7月8日)

Swift による、macOS 用のドラッグアンドドロップに対応した簡単な動画再生アプリのサンプルです。

AVPlayerView にいくつかのメソッドをオーバーライドすることで、動画ファイルを Finder からドラッグアンドドロップで読み込めます。

サンプルアプリの動作

以下のように、ファイルをアプリのウィンドウにドラッグアンドドロップすると、その動画ファイルが読み込まれます。

AVPlayerViewに動画をドラッグアンドドロップ

サンプルのコード

Cocoa App」として新規作成したプロジェクトの ViewController.swift を以下のように書き換えます。

ウィンドウサイズは Storyboard 上でプロパティを変更し 800×600 としています。

import Cocoa
import AVFoundation
import AVKit

class ViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 動画プレイヤー
        let playerView = MyAVPlayerView(frame: self.view.frame)
        
        // .floating にすると QuickTimePlayer の様にコントローラを動かせる
        playerView.controlsStyle = AVPlayerViewControlsStyle.floating
        
        // フルスクリーン化するボタンを表示
        playerView.showsFullScreenToggleButton = true
        
        self.view.addSubview(playerView)
    }
    
    override var representedObject: Any? {
        didSet {
            // Update the view, if already loaded.
        }
    }
}

// ドロップされた動画を読み込むAVPlayerView
class MyAVPlayerView: AVPlayerView {
    
    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        
        // ドラッグでファイルURLを取得するための設定
        self.registerForDraggedTypes([NSPasteboard.PasteboardType.fileURL])
    }
    
    required init?(coder decoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // ドラッグしながら領域に入ったときの処理
    override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
        
        print("dragging entered")
        
        return .link
    }
    
    // 領域にドロップしたときの処理
    override func draggingEnded(_ sender: NSDraggingInfo) {
        
        print("dragging ended")

        if !self.frame.contains(sender.draggingLocation()) {
            // ドロップ位置がビューの外側だったら何もしない
            print("drop outside")
            return
        }
        
        if let draggedFilePath = sender.draggingPasteboard().propertyList(
                        forType: NSPasteboard.PasteboardType(rawValue: "NSFilenamesPboardType")) as? [String] {
            
            if let path = draggedFilePath.first {
                // ドロップされたファイルのパスから動画を読み込む
                
                print(path)
                
                let url = URL(fileURLWithPath: path)
                let asset = AVAsset(url: url)
                let playerItem = AVPlayerItem(asset: asset)
                
                self.player = AVPlayer(playerItem: playerItem)
            }
        }
    }
}

マウスが AVPlayerView の領域に入ると draggingEntered が、ドロップすると draggingEnded が呼び出されます。

このコードには動画ファイル以外のドロップを防止する処理がないため、テキストファイルなどをドロップすると、プレイヤーが以下のように表示されます。

動画ファイル以外をドラッグアンドドロップしたプレイヤー

以上が、ドラッグアンドドロップによる動画読み込みを行う最低限のサンプルプログラムでした。

コメントを残す

メールアドレスが公開されることはありません。