Hello,
I try to fetch data from my API every 5 seconds. I did this code, but it does not work. Any ideas what I'm doing wrong?
let urlString = "https://radio.app/api/nowplaying/radio_x"
let url = URL(string: urlString)!
let session = URLSession.shared
let dataTask = session.dataTask(with: url) { data, response, error in
if let error = error {
print(error)
return
}
guard let data = data else {
print("data is nil")
return
}
let decoder = JSONDecoder()
do {
let radio = try decoder.decode(RadioAPI.self, from: data)
print(radio)
DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: {
//this is the line that I've added DispatchQueue.main.asyncDispatchQueue.main.asyncAfter insted of standard
self.songtitle.text = radio.nowPlaying.song.title
self.artist.text = radio.nowPlaying.song.artist
//albumcover art section
if let artUrl = URL(string: radio.nowPlaying.song.art) {
//I need to load an image from `artUrl`
let imageDatatask = session.dataTask(with: artUrl) { imageData, imageResponse, imageError in
if let error = error {
print(error)
return
}
guard let imageData = imageData else {
print("image_data is nil")
return
}
//let albumArt = UIImage(data: imageData)
DispatchQueue.main.async {
let albumArt = UIImage(data: imageData)
let albumView = UIImageView(image: albumArt)
}
}
imageDatatask.resume()
}
})
}
catch {
print("Error Parsing JSON: \(error)")
}
}
dataTask.resume()
}
Thanks for showing your code. Generally, easily triable code would help involving more readers. Very few people would dive into the external links, even though they are safe enough as GitHub.
And have you tried Paste and Match Style as suggested by Claude31? It will help preventing extra empty lines added.
Seems you use asyncAfter
in the wrong place. You need to trigger fetching the next nowPlaying
after the current nowPlaying
is processed.
Please try something like this:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
overrideUserInterfaceStyle = .light
setupRemoteCommandCenter()
requestNowPlaying()
}
private var songArtUrl: URL? = nil
private func requestNowPlaying() {
//Radio API endpoint title and artist labels
let urlString = "https://admin.radiopromil.online/api/nowplaying/radio_promil"
let url = URL(string: urlString)!
let session = URLSession.shared
let dataTask = session.dataTask(with: url) { data, response, error in
if let error = error {
print(error)
return
}
guard let data = data else {
print("data is nil")
return
}
let decoder = JSONDecoder()
do {
let radio = try decoder.decode(RadioAPI.self, from: data)
print(radio)
DispatchQueue.main.async {
self.songtitle.text = radio.nowPlaying.song.title
self.artist.text = radio.nowPlaying.song.artist
//albumcover art section
if let artUrl = URL(string: radio.nowPlaying.song.art),
artUrl != self.songArtUrl {
//I need to load an image from `artUrl`
let imageDatatask = session.dataTask(with: artUrl) { imageData, imageResponse, imageError in
if let imageError = imageError {
print(imageError)
return
}
guard let imageData = imageData else {
print("image_data is nil")
return
}
DispatchQueue.main.async {
self.songArtUrl = artUrl
let albumArt = UIImage(data: imageData)
//↓ Assuming you connected `artUrl` to the right UIImageView
//Generally, naming `...Url` for a property of type `UIImageView` may be confusing...
self.artUrl.image = albumArt
}
}
imageDatatask.resume()
}
let intervalToNextRequest = radio.nowPlaying.remaining ?? 5 // Re-consider if this is appropriate
print("intervalToNextRequest=\(intervalToNextRequest)")
DispatchQueue.main.asyncAfter(deadline: .now() + TimeInterval(intervalToNextRequest)) {
print("Next request triggered...")
self.requestNowPlaying()
}
}
} catch {
print("Error Parsing JSON: \(error)")
}
}
dataTask.resume()
}