首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SwiftUI中的MPMediaPickerController?

SwiftUI中的MPMediaPickerController?
EN

Stack Overflow用户
提问于 2020-07-28 07:52:23
回答 3查看 626关注 0票数 1

我正在用SwiftUI重建我的一个应用程序,但我遇到了一个问题。

我的问题是..我的应用程序是一个AudioVisual测试生成器,目前能够从用户设备的音乐库中选择一首测试歌曲,并将该歌曲设置为应用程序的测试歌曲。其他测试包括Left Speaker、Right Speaker等,但此功能允许用户从设备的库中选择自己的自定义测试歌曲(或者默认为默认测试歌曲)。

我的应用程序目前是用Swift编写的,它使用MPMediaPickerController来选择歌曲,它工作得很好。然而,我真的很难让音乐库拾取器控制器在我的SwiftUI重建中工作。有谁知道在SwiftUI中访问用户音乐库的可靠方法?

我一直被不符合类协议'NSObjectProtocol‘的对象卡住,这让我相信有一种更快速的方法来做到这一点?或者我可以在我的大部分应用程序中使用SwiftUI,但可以过渡到UIView来选择歌曲?

这里有一些还不能工作的代码,它很不错..我只是想尽我所能来解决这个问题,并计划如果我能让它正常工作,就进行重构。

//可能导入了比我需要的更多的东西。

代码语言:javascript
复制
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")

    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-08-20 20:24:38

这个解决方案几乎完全基于Dave在7月28日的帖子。前面的代码还没有选择歌曲并将其传递给View的方法。在下面的示例中,它将所选歌曲传递给@EnvironmentObject,但它也可以像Dave建议的那样轻松地与@Binding一起使用。

代码语言:javascript
复制
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>) {
    }

}
票数 1
EN

Stack Overflow用户

发布于 2020-07-28 11:44:51

UIViewControllerRepresentable是SwiftUI视图,因此必须是结构

代码语言:javascript
复制
struct SongPickerController: UIViewControllerRepresentable

但是UIViewController是UIKit类,所以继承的实体必须是类

代码语言:javascript
复制
class SongUIView: UIViewController
票数 1
EN

Stack Overflow用户

发布于 2020-07-28 23:11:34

在用户Asperi将我推向正确的方向后,我想分享我的最终代码,以便在SwiftUI中呈现音乐库。这是第一部分...

代码语言:javascript
复制
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

代码语言:javascript
复制
@State private var song: Song?
@State private var showingSongPicker = false

并使用此按钮显示媒体选取器

代码语言:javascript
复制
    Button(action: {
        self.showingSongPicker = true
    }
    ){
        Text("Edit Test Song")
    }
    .sheet(isPresented: $showingSongPicker) {
        MusicPicker(song: self.$song)
    }

注意:我仍在处理一些Apple Music Token问题,新测试歌曲的选择还不起作用。但是介绍音乐选择器的部分就是这个问题是关于什么的,现在它起作用了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63125173

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档