我正在用SwiftUI重建我的一个应用程序,但我遇到了一个问题。
我的问题是..我的应用程序是一个AudioVisual测试生成器,目前能够从用户设备的音乐库中选择一首测试歌曲,并将该歌曲设置为应用程序的测试歌曲。其他测试包括Left Speaker、Right Speaker等,但此功能允许用户从设备的库中选择自己的自定义测试歌曲(或者默认为默认测试歌曲)。
我的应用程序目前是用Swift编写的,它使用MPMediaPickerController来选择歌曲,它工作得很好。然而,我真的很难让音乐库拾取器控制器在我的SwiftUI重建中工作。有谁知道在SwiftUI中访问用户音乐库的可靠方法?
我一直被不符合类协议'NSObjectProtocol‘的对象卡住,这让我相信有一种更快速的方法来做到这一点?或者我可以在我的大部分应用程序中使用SwiftUI,但可以过渡到UIView来选择歌曲?
这里有一些还不能工作的代码,它很不错..我只是想尽我所能来解决这个问题,并计划如果我能让它正常工作,就进行重构。
//可能导入了比我需要的更多的东西。
import UIKit
import SwiftUI
import AVFoundation
import AVKit
import MediaPlayer
class SongPickerController: UIViewControllerRepresentable, MPMediaPickerControllerDelegate {
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIImagePickerController {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = context.coordinator
return imagePickerController
}
func makePickerController(context: Context) -> MPMediaPickerController {
var picker = MPMediaPickerController()
picker = MPMediaPickerController(mediaTypes: .anyAudio)
//picker.delegate = self
picker.allowsPickingMultipleItems = false
picker.showsCloudItems = false
picker.prompt = NSLocalizedString(Texts.pickerDetail, comment: Texts.pickerComment)
return picker
}
func songSelectButtonClicked () {
picker = MPMediaPickerController(mediaTypes: .anyAudio)
picker?.delegate = self
picker?.allowsPickingMultipleItems = false
picker?.showsCloudItems = false
picker?.prompt = NSLocalizedString(Texts.pickerDetail, comment: Texts.pickerComment)
self.present(picker!, animated: false, completion: nil)
func updateUIViewController(_ uiViewController: MPMediaPickerController, context: Context) {
}
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var parent: SongPickerController
init(_ imagePickerController: SongPickerController) {
self.parent = imagePickerController
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)}}}}
struct SongUIView: UIViewController, MPMediaPickerControllerDelegate {
var picker: MPMediaPickerController?
func songSelectButtonClicked () {
picker = MPMediaPickerController(mediaTypes: .anyAudio)
picker?.delegate = self
picker?.allowsPickingMultipleItems = false
picker?.showsCloudItems = false
picker?.prompt = NSLocalizedString(Texts.pickerDetail, comment: Texts.pickerComment)
self.present(picker!, animated: false, completion: nil)
}
func mediaPicker(_ mediaPicker: MPMediaPickerController,
didPickMediaItems mediaItemCollection: MPMediaItemCollection){
let selectedSong = mediaItemCollection.items
if (selectedSong.count) > 0 {
let songItem = selectedSong[0]
let songURL = songItem.value(forProperty: MPMediaItemPropertyAssetURL)
let saveString = "\(songURL!)"
let saveTitle = "\(songItem.title!) by \(songItem.artist!)"
saveDefaultSong(saveString as NSString, title: saveTitle as NSString)
mediaPicker.dismiss(animated: true, completion: nil)
///selectSongButton.setTitle("Custom song assigned!", for: UIControl.State())
}
}
func mediaPickerDidCancel(_ mediaPicker: MPMediaPickerController) {
mediaPicker.dismiss(animated: true, completion: nil)
}
func saveDefaultSong (_ name: NSString, title: NSString) {
UserDefaults.standard.set(name, forKey: "Default Song")
UserDefaults.standard.set(title, forKey: "Default Song Title")
}
}发布于 2020-08-20 20:24:38
这个解决方案几乎完全基于Dave在7月28日的帖子。前面的代码还没有选择歌曲并将其传递给View的方法。在下面的示例中,它将所选歌曲传递给@EnvironmentObject,但它也可以像Dave建议的那样轻松地与@Binding一起使用。
import SwiftUI
import MediaPlayer
struct MusicPicker: UIViewControllerRepresentable {
@Environment(\.presentationMode) var presentationMode
@EnvironmentObject var player: AudioPlayer
class Coordinator: NSObject, UINavigationControllerDelegate, MPMediaPickerControllerDelegate {
var parent: MusicPicker
init(_ parent: MusicPicker) {
self.parent = parent
}
func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
let selectedSong = mediaItemCollection.items
if (selectedSong.count) > 0 {
let songItem = selectedSong[0]
parent.setSong(song: songItem)
mediaPicker.dismiss(animated: true, completion: nil)
}
}
}
func setSong(song: MPMediaItem) {
player.setAudioTrack(song: song)
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<MusicPicker>) -> MPMediaPickerController {
let picker = MPMediaPickerController()
picker.allowsPickingMultipleItems = false
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: MPMediaPickerController, context: UIViewControllerRepresentableContext<MusicPicker>) {
}
}发布于 2020-07-28 11:44:51
UIViewControllerRepresentable是SwiftUI视图,因此必须是结构
struct SongPickerController: UIViewControllerRepresentable但是UIViewController是UIKit类,所以继承的实体必须是类
class SongUIView: UIViewController发布于 2020-07-28 23:11:34
在用户Asperi将我推向正确的方向后,我想分享我的最终代码,以便在SwiftUI中呈现音乐库。这是第一部分...
import SwiftUI
import MediaPlayer
//MUSIC PICKER.. WORKING
struct MusicPicker: UIViewControllerRepresentable {
@Environment(\.presentationMode) var presentationMode
@Binding var song: Song?
class Coordinator: NSObject, UINavigationControllerDelegate, MPMediaPickerControllerDelegate {
var parent: MusicPicker
init(_ parent: MusicPicker) {
self.parent = parent
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<MusicPicker>) -> MPMediaPickerController {
let picker = MPMediaPickerController()
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: MPMediaPickerController, context: UIViewControllerRepresentableContext<MusicPicker>) {
}
}然后,为了在我的SwiftUI视图中调用它,我声明了一对@State var
@State private var song: Song?
@State private var showingSongPicker = false并使用此按钮显示媒体选取器
Button(action: {
self.showingSongPicker = true
}
){
Text("Edit Test Song")
}
.sheet(isPresented: $showingSongPicker) {
MusicPicker(song: self.$song)
}注意:我仍在处理一些Apple Music Token问题,新测试歌曲的选择还不起作用。但是介绍音乐选择器的部分就是这个问题是关于什么的,现在它起作用了。
https://stackoverflow.com/questions/63125173
复制相似问题