Search code examples
swiftswiftuiswiftui-listapple-musicapple-musickit

MPMediaItem array not printing song titles in SwiftUI List


I have a Swift project that prints a list of songs in a table view. Below is the basis of the current working code for retrieving and putting those songs in rows.

Swift:

var mySongs: [MPMediaItem] = []

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let song = mySongs[indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        let myText = song.title
        cell.textLabel?.text = myText; return cell
}

I am trying to move this code over to SwiftUI.

Swift UI:

private var mySongs: [MPMediaItem] = []

var body: some View {
    
    List {
        let song = mySongs[indexPath.row]
        let myText = song.title
        
        ForEach(self.mySongs, id: \.self) {
            item in Text(myText)
        }
    }
    
}

However, SwiftUI doesn't allow me to track the path of every element. Even when I try to substitute the myText for mySongs.title to eliminate the need for indexPath, it fails.

ForEach(self.mySongs, id: \.self) {
            item in Text(mySongs.title)
}

Giving me a Value of type '[MPMediaItem]' has no member 'title' error.

I thought maybe I am doing the for-each on this completely wrong so I headed to see other methods such as https://learnappmaking.com/swiftui-list-foreach-how-to/ what's on this site, but when implementing I got the same results and was just as unsuccessful.

What am I missing or where should I look to fix the issue?


Solution

  • Looks like you were on the right track -- just a little bit of confusion about what ForEach provides in the closure, I think.

    This should work:

    private var mySongs: [MPMediaItem] = []
    
    var body: some View {
      List {
        ForEach(mySongs, id: \.self) { item in
          Text(item.title ?? "unknown title")
        }
      }
    }
    

    item gives you the current element that ForEach is iterating over, so there's actually no reason to use the index. Since title is a String? and Text requires a non-optional String, you have to provide a default value if there isn't a title present.