Я пытаюсь запустить простой http-запрос к API Spotify, чтобы получить последние воспроизведенные треки.
"https://api.spotify.com/v1/me/player/recently-played?limit=2&before=1676369852305"
Все работает, и я получаю результат обратно, но когда я добавляю идентифицируемый протокол с переменной id к своим объектам структуры, декодер дает сбой (ноль). (Я хочу соответствовать Идентифицируемым, потому что мне нужно использовать данные в цикле List/ForEach
Вот мой код
//objects
struct Recent: Codable { //or Codable, Identifiable
//let id: UUID?
let items: [Item]?
let next: String?
let limit: Int?
let href: String?
}
struct Item: Codable { //or Codable, Identifiable
// let id: UUID?
let track: Track?
let played_at: String?
}
struct Track: Codable { //or Codable, Identifiable
//let id: String?
let name: String?
let popularity: Int?
let trackNumber: Int?
let type, uri: String?
}
//function
func getRecentPlayed(miliTime: String) {
//let miliTime = "1676369852305"
let urlString = "https://api.spotify.com/v1/me/player/recently-played?limit=10&before=\(miliTime)"
let url = URL(string: urlString)
let urlSessionConfig = URLSessionConfiguration.default
urlSessionConfig.httpAdditionalHeaders = ["Authorization": "Bearer \(OAuthToken)"]
let urlSession = URLSession(configuration: urlSessionConfig)
let sessionTask = urlSession.dataTask(with: url!) { data, response, error in
if (error == nil && data != nil) {
let jsondecoder = JSONDecoder()
let recentPlayedData = try? jsondecoder.decode(Recent.self, from: data!)
print (recentPlayedData)
recent = recentPlayedData
} else {
print (error)
}
}
sessionTask.resume()
}
Что я хочу: Запустите следующий цикл в swiftui, но он кричит:
"Referencing initializer on 'ForEach' requires that 'Item' conform to 'Identifiable"
//swiftui
@State var recent: Recent?
if let r = recent {
NavigationView {
List {
ForEach(r.items!) { item in
Text((item.track?.name)!)
}
}
.navigationTitle("Recently played")
}
}
Любая идея?
id
опущен. я не получаю никакой ошибки, но он запрашивает идентификацию, хочу ли я использовать объект с ForEach
. Я постараюсь добавить CodingKeys и дам вам знать
Свойство id для Identifiable должно быть необязательным. Напишите let id = UUID() и добавьте CodingKeys.
Я попробовал это с CodingKeys enum, и это тоже сработало. Большое спасибо!
Вы можете использовать то, что у вас есть, что уже уникально
struct Recent: Codable {
var id: String?{
href
}
let items: [Item]?
let next: String?
let limit: Int?
let href: String?
}
struct Item: Codable, Identifiable {
var id:String?{
track?.id
}
let track: Track?
let played_at: String?
}
struct Track: Codable, Identifiable { //or Codable, Identifiable
var id: String?{
uri
}
let name: String?
let popularity: Int?
let trackNumber: Int?
let type, uri: String?
}
Большое спасибо, это сработало! Это было очень умно, если честно. Хорошего настроения :)
@ ccmsd18 рад помочь, не могли бы вы нажать на зеленую галочку, чтобы принять ответ и, возможно, проголосовать?
Это невозможно именно так, как вы хотите, я думаю, что самое близкое к тому, что вы хотите, это:
struct Track: Codable, Identifiable{ //or
let id = UUID() //or something else, it is not clear what is your id
let name: String?
let popularity: Int?
let trackNumber: Int?
let type, uri: String?
}
Не try?, никогда try?, вы игнорируете важную информацию; catch ошибку и распечатать. Он сообщает вам keyNotFound. Вы должны добавить CodingKeys и опустить id. И почему все опционально? Тем более объявлять id необязательным бессмысленно.