SwiftUI 通過UIViewControllerRepresentable protocol來封裝AVPlayerViewController
xcode 13.4.1, swift 5.5, iOS 15.4
2022-09-09
SwiftUI雖然已經提供了很多內建的元件,但SwiftUI還沒有UIKit成熟,所以有些時候需要借助UIKit來實現,要做這個工作,就要通過SwiftUI提供的UIViewControllerRepresentable protocol來與UIKit中的視圖控制器 (View Controller)作橋樑溝通,這次試試把AVPlayerViewController打包成View來在SwiftUI里面使用。
1. 在itune上選一首自己喜歡的preview的歌,我這里選了這首
Light Year的歌,並將其下載及放到project中,並使用
SwiftUI 使用Bundle讀取已預先在Project中檔案的方法來創建URL:
2. 使用一個song class來封裝,將一個檔案轉成一個URL,以便後面容易的使用。
class Song {
let songName : String
let songExtension : String
var songUrl : URL?
init( _ songName : String , _ songExtension : String ) {
self.songName = songName
self.songExtension = songExtension
guard let soundPath = Bundle.main.path(forResource: "LightYear", ofType: "m4a") else {
return
}
self.songUrl = URL(fileURLWithPath: soundPath)
}
}
3. 實現一個UIViewControllerRepresentable的View AudioPlayerView,在makeUIViewController方法中,創建立返回AVPlayerViewController,就實現使用AVPlayerViewController的橋梁:
import SwiftUI
import AVKit
struct AudioPlayerView : UIViewControllerRepresentable {
let url : URL
func makeUIViewController(context: Context) -> AVPlayerViewController {
let player = AVPlayer(url: url)
let viewController = AVPlayerViewController()
viewController.player = player
viewController.entersFullScreenWhenPlaybackBegins = true
player.play()
return viewController
}
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {
}
}
4. 最後就是來看看如何使用AudioPlayerView,以下程式就是按下play的按鈕,就顯示AudioPlayerView並自動播放音樂:
import SwiftUI
import AVKit
struct AudioPlayerView : UIViewControllerRepresentable {
let url : URL
func makeUIViewController(context: Context) -> AVPlayerViewController {
let player = AVPlayer(url: url)
let viewController = AVPlayerViewController()
viewController.player = player
viewController.entersFullScreenWhenPlaybackBegins = true
player.play()
return viewController
}
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {
}
}
class Song {
let songName : String
let songExtension : String
var songUrl : URL?
init( _ songName : String , _ songExtension : String ) {
self.songName = songName
self.songExtension = songExtension
guard let soundPath = Bundle.main.path(forResource: "LightYear", ofType: "m4a") else {
return
}
self.songUrl = URL(fileURLWithPath: soundPath)
}
}
struct AudioPlayerExample: View {
@State var playFlag = false
let song = Song("LightYear", "m4a")
var body: some View {
Button(action: {
if self.song.songUrl != nil {
self.playFlag = true
}
}, label: {
Text("Play")
})
.sheet(isPresented: $playFlag) {
AudioPlayerView(url : self.song.songUrl!)
}
}
}