I am attempting to dynamically show the contents of YouTube playlist in my SwiftUI IOS app.
I have managed to obtain the relevant information from the API call but am struggling with the leap to saving the items as an array of Videos to then show in the SwiftUI view. The response itself at the moment is a list of videos.
Video Model
struct Video: Decodable, Hashable {
var title = ""
var description = ""
var thumbnail = ""
var videoId = ""
// map variables to coded properties in JSON
enum CodingKeys: String, CodingKey {
// additional higher level keys so that we can access the nested variables
case snippet
case thumbnails
case high
case resourceId
// general keys - have to make sure these match the JSON keys
case videoId
case title
case description
case thumbnail = "url"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let snippetContainer = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .snippet)
// parse title
self.title = try snippetContainer.decode(String.self, forKey: .title)
// parse description
self.description = try snippetContainer.decode(String.self, forKey: .description)
// parse thumbnail - needed to drill down into further nests
let thumbnailContainer = try snippetContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .thumbnails)
let highContainer = try thumbnailContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .high)
self.thumbnail = try highContainer.decode(String.self, forKey: .thumbnail)
// parse videoId
let resourceContainer = try snippetContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .resourceId)
self.videoId = try resourceContainer.decode(String.self, forKey: .videoId)
}
}
// the containers that are referenced above are in a items dictionary in the high level
struct Response: Decodable, Hashable {
var items: [Video]?
enum CodingKeys: String, CodingKey {
case items
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.items = try container.decode([Video].self, forKey: .items)
}
}
View Model (the response prints)
class VideoModel: ObservableObject {
func getVideos() {
// create a URL object
let url = URL(string: Constants.API_URL)
//return if the API_url is blank
guard url != nil else {
return }
// get a URLsession object
let session = URLSession.shared
// get a data task from URLsession object
let dataTask = session.dataTask(with: url!) {(data, response, error) in
// check if there is an error
if error != nil || data == nil {
return}
do {
// parsing the data into video objects
let decorder = JSONDecoder()
let response = try decorder.decode(Response.self, from: data!)
}
catch {
print(error)
}
}
dataTask.resume()
}
}
SwiftUI view - incomplete as new to create a row view.
struct PlayListView: View {
var viewModel = VideoModel()
var body: some View {
NavigationView {
ScrollView {
List {
ForEach(viewModel.response.items, id: \.self) { video in
Text(video.title)
}
}
}
.navigationTitle("The GB Way")
.onAppear() {
viewModel.getVideos()
}
}
}
}
Thank you in advance for any help