This is a followup to SwiftUI Table does not work when trying to use Int values
After getting a result from looking up an album or song in AppleMusic API, I parse the returned json using SwiftyJSON as shown here:
URLSession.shared.dataTask(with: musicRequest) { (data, response, error) in
guard error == nil else { return }
if let json = try? JSON(data: data!) {
let result = (json["data"]).array!
for songDetail in result {
let attributes = songDetail["attributes"]
let song = SongDetails(albumName: attributes["albumName"].string!,
artistName: attributes["artistName"].string!,
artworkURL: attributes["artwork"]["url"].string!,
composerName: attributes["composerName"].string ?? "-",
discNumber: attributes["discNumber"].int!,
durationInMillis: attributes["durationInMillis"].int!,
genreNames: attributes["genreNames"].arrayValue,
isrc: attributes["isrc"].string!,
name: attributes["name"].string!,
id: attributes["playParams"]["id"].string!,
releaseDate: attributes["releaseDate"].string!,
trackNumber: attributes["trackNumber"].int!)
songDetails.append(song)
print(songDetails)
}
Notice how [genreNames] needs ".arrayValue" instead of ".string!". I Think the reason is because "genreNames" are listed in an Array of Strings.
Here is the data model I use for the parsed results:
struct SongDetails {
var albumName: String
var artistName: String
var artworkURL: String
var composerName: String
var discNumber: Int
var durationInMillis: Int
var genreNames: Array<Any>
var isrc: String
var name: String
var id: String
var releaseDate: String
var trackNumber: Int
init(albumName: String, artistName: String, artworkURL: String, composerName: String, discNumber: Int, durationInMillis: Int, genreNames: Array<Any>, isrc: String, name: String, id: String, releaseDate: String, trackNumber: Int) {
self.albumName = albumName
self.artistName = artistName
self.artworkURL = artworkURL
self.composerName = composerName
self.discNumber = discNumber
self.durationInMillis = durationInMillis
self.genreNames = genreNames
self.isrc = isrc
self.name = name
self.id = id
self.releaseDate = releaseDate
self.trackNumber = trackNumber
}
}
Here I have genreNames as "Array". This set up works and I can call and print jus the genreNames, but everything I have read online says that "[String]" should be used instead of "Array", but if I do that, I get an error in the previous code when using [genreNames].string!. The way I currently have it set up, genreNames show up in the console as genreNames: [Pop, Music]
, so I think it is correct. The issue arises when I try to use genreNames in a SwiftUI view.
In my SwiftUI view I have a Table where these results go.
HStack {
WebImage(url: URL(string: songDetail.artworkURL.replacingOccurrences(of: "{w}", with: "5000").replacingOccurrences(of: "{h}", with: "5000")))
.resizable()
.indicator(.activity)
.frame(width: 400, height: 400)
.cornerRadius(5)
.shadow(radius: 2)
VStack (alignment: .leading) {
Text("song id: \(songDetail.id)")
.foregroundColor(.secondary)
.padding(2)
Text("title: \(songDetail.name)")
.foregroundColor(.secondary)
.padding(2)
Text("artist: \(songDetail.artistName)")
.foregroundColor(.secondary)
.padding(2)
Text("composer: \(songDetail.composerName)")
.foregroundColor(.secondary)
.padding(2)
Text("disc number \(songDetail.discNumberString)")
.foregroundColor(.secondary)
.padding(2)
Text("track number: \(songDetail.trackNumberString)")
.foregroundColor(.secondary)
.padding(2)
Text("duration in ms: \(songDetail.durationInMillisString)")
.foregroundColor(.secondary)
.padding(2)
Text("release date: \(songDetail.releaseDate)")
.foregroundColor(.secondary)
.padding(2)
Text("isrc: \(songDetail.isrc)")
.foregroundColor(.secondary)
.padding(2)
}
.font(.system(size: 14))
}
}
}.padding(.leading, 20.0)
.frame(minWidth:800, idealWidth: 1000, maxWidth: .infinity, minHeight:600, idealHeight: 800, maxHeight: .infinity)
.onAppear {
SKCloudServiceController.requestAuthorization { (status) in
if status == .authorized {
self.searchResults = AppleMusicAPI().getSongDetails(self.songId)
}
}
}
}
}
extension SongDetails {
var discNumberString: String {
String(discNumber)
}
var trackNumberString: String {
String(trackNumber)
}
var durationInMillisString: String {
String(durationInMillis)
}
}
The extension at the bottom is how the issue of the original post was solved. It seems that the new SwiftUI Table can only accept String values. To get the genreNames into this table I tried making a similar extension where I used join() to try and make a string of the genreResults, but that did not work either. I can't remember the exact code, but it could have been wrong.
So how would this be accomplished? Anyone know? This is the last thing that I need to get into my Table. Thanks! I appreciate the help!