如何在 SwiftUI 列表中显示 MPMediaItem 图稿?

Posted

技术标签:

【中文标题】如何在 SwiftUI 列表中显示 MPMediaItem 图稿?【英文标题】:How to show MPMediaItem Artwork in a SwiftUI list? 【发布时间】:2019-10-17 14:49:39 【问题描述】:

我尝试在我的 iPhone 上构建所有本地存储歌曲的 SwiftUI 列表。我使用 Apple 的 MediaPlayer 框架来获取歌曲并将它们存储在 EnvironmentObject 中,以便在我的 SwiftUI 视图中轻松访问。

在我的 Cell 中,我通过访问图像,但我得到的只是一个白色的 50x50 块:

Image(uiImage: self.item.artwork!.image(at: CGSize(width: 50, height: 50))!)

结果:https://i.imgur.com/gulvJ8u.png

// EnvironmentObject
class UserData: ObservableObject 

    @Published var allowMusicLibraryAccess: Bool = false
    @Published var songs: [MPMediaItem]

    init() 
        self.songs = [MPMediaItem]()

        self.initAllowMusicLibraryAccess()
    

    private func initAllowMusicLibraryAccess() -> Void 
        MPMediaLibrary.requestAuthorization  status in
            if status == .authorized 
                DispatchQueue.main.async 
                    self.allowMusicLibraryAccess = true
                    self.songs = MPMediaQuery.songs().items!
                
            
        
    

// List
struct ContentView: View 

    @EnvironmentObject var userData: UserData

    var body: some View 
        ZStack() 
            if self.userData.allowMusicLibraryAccess 
                NavigationView 
                    List 
                        ForEach(self.userData.songs, id: \.persistentID)  song in
                            SongCell(song)
                        
                    
                    .navigationBarTitle("Songs")
                
             else 
                Text("Music Library Access needed")
            
        
    

// Cell
struct SongCell: View 

    let item: MPMediaItem

    init(_ item: MPMediaItem) 
        self.item = item
    

    var body: some View 

        Button(action: 
            print("clicked \(self.item)")
        ) 
            HStack() 
                if self.item.artwork != nil 
                    Image(uiImage: self.item.artwork!.image(at: CGSize(width: 50, height: 50))!)
                        .resizable()
                        .frame(width: 50, height: 50)
                        .cornerRadius(4)
                

                VStack(alignment: .leading) 
                    Text(self.item.title ?? "---")

                    Text(self.item.artist ?? "---")
                        .font(.system(.footnote))
                        .opacity(0.7)
                
            
        
        .frame(minWidth: nil, idealWidth: nil, maxWidth: .infinity, minHeight: 55, idealHeight: 55, maxHeight: 55, alignment: .leading)
    

【问题讨论】:

【参考方案1】:

解决方法是使用 .renderingMode() 修饰符:

Image(uiImage: self.item.artwork!.image(at: CGSize(width: 50, height: 50))!)
    .renderingMode(.original)

【讨论】:

【参考方案2】:

我确实想通了,但它看起来有点像一个错误或一些我无法解释的非常有趣的初始化行为。

我发现将 Image 移出 Cell 并直接移入 List ForEach 可以解决这个问题。就像我说的,我无法解释为什么会这样。

// Cell
struct SongCell: View 

    let item: MPMediaItem

    init(_ item: MPMediaItem) 
        self.item = item
    

    var body: some View 

        Button(action: 
            print("clicked \(self.item)")
        ) 
            VStack(alignment: .leading) 
                Text(self.item.title ?? "---")

                Text(self.item.artist ?? "---")
                    .font(.system(.footnote))
                    .opacity(0.7)
            
        
        .frame(minWidth: nil, idealWidth: nil, maxWidth: .infinity, minHeight: 55, idealHeight: 55, maxHeight: 55, alignment: .leading)
    

// List
struct ContentView: View 

    @EnvironmentObject var userData: UserData

    var body: some View 
        ZStack() 
            if self.userData.allowMusicLibraryAccess 
                NavigationView 
                    List 
                        ForEach(self.userData.songs, id: \.persistentID)  song in
                            HStack() 
                                Image(uiImage: song.artwork!.image(at: CGSize(width: 50, height: 50))!)
                                    .resizable()
                                    .frame(width: 50, height: 50)
                                    .cornerRadius(4)
                                SongCell(song)
                                
                         
                    
                    .navigationBarTitle("Songs")
                
             else 
                Text("Music Library Access needed")
            
        
     

【讨论】:

以上是关于如何在 SwiftUI 列表中显示 MPMediaItem 图稿?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SwiftUI 列表中显示领域结果?

如何在 SwiftUI 中使用 .fileimporter 保存音频文件并检索文件并在 SwiftUI 列表中显示它们的文件名?

如何在 SwiftUI 中清除列表项上的默认突出显示灰色?

如何在切换 SwiftUI 中使用 json 属性?

如何有效地过滤 SwiftUI 中的长列表?

如何居中水平图像列表SwiftUI