[英]How to show MPMediaItem Artwork in a SwiftUI list?
我嘗試在我的 iPhone 上構建一個 SwiftUI 列表,其中包含所有本地存儲的歌曲。 我使用 Apple 的 MediaPlayer Framework 來獲取歌曲並將它們存儲在 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)
}
}
解決方案是使用 .renderingMode() 修飾符:
Image(uiImage: self.item.artwork!.image(at: CGSize(width: 50, height: 50))!)
.renderingMode(.original)
用 iOS 15,
我們可以用
ArtworkImage (artwork: self.item.artwork, width: 250) // 指定寬度
我確實弄明白了,但它似乎有點像一個錯誤或一些我無法解釋的非常有趣的初始化行為。
我發現將 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")
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.