Search code examples
swiftconcurrencyswift-playgroundurlsession

Why is URLSession not returning data in playground?


I cannot understand why this URLSession is not working on my playground. The URL works fine using curl commands on my terminal, so I know it is active, but I cannot see any list of names printed on my console.

The only print I see is the one "called" after that one, it seems there must be some error, but I have no clue about it, no message. Issue must be around the URLSession but cannot get where.

UPDATE

I added an extension to data found on stack, using right after this code

let (data, response) = try await URLSession.shared.data(from: url)
data.printJson()

The data is printed, but still cannot print anything in the for loop, where it should be.

extension Data {
           
    func printJson() {
        do {
            let json = try JSONSerialization.jsonObject(with: self, options: [])
            let data = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
            guard let jsonString = String(data: data, encoding: .utf8) else {
                print("Invalid data")
                return
            }
            print(jsonString)
        } catch {
            print("Error: \(error.localizedDescription)")
        }
    }
}

And

import Foundation

//-----------------------------------------------
//MARK: - model
//-----------------------------------------------

struct ResponseRandom: Codable {
    let users: [User]
}

struct User: Codable, Identifiable {
    
    let id: Int
    let first_name: String
    let email: String
    //    "avatar": "https://robohash.org/rationeetsit.png?size=300x300&set=set1"
    let date_of_birth: String//"1958-07-18"
    
}


//-----------------------------------------------
//MARK: - class
//-----------------------------------------------


class HTTPRequest_randomUsers {
    
    //    @Published var users = [UserRandom]()
    
    init() {
        Task {
            await loadData()
        }
    }
    
    func loadData() async {
        print("called")
        
        let numberOfItems = 50
        
        guard let url = URL(string: "https://random-data-api.com/api/v2/users?size=2&response_type=json") else {
            fatalError("URL error")
        }
        
    
        do {
            let (data, response) = try await URLSession.shared.data(from: url)

            guard let response = response as? HTTPURLResponse else {
                print("not valid response")
                return}
            
            guard response.statusCode == 200 else {
                print("not 200 status")
                return}
            
            let decoded = try JSONDecoder().decode([User].self, from: data)
            print("decoded")
            
            await MainActor.run {
                //                    users = decoded.users
                for item in decoded {
                    print(item.first_name)
                }
            }
            
            
        } catch {
            print("error: \(error)")
        }
        
    }
    
}

//here my call
let c = HTTPRequest_randomUsers()

Solution

  • Network requests run asynchronously (i.e., finish later). But by default, simple Playgrounds will stop when they reach the end of their path of execution. One must tell the Playground to continue execution indefinitely in order for the asynchronous results to be retrieved successfully:

    import PlaygroundSupport
    

    and

    PlaygroundPage.current.needsIndefiniteExecution = true