Home > front end >  Can't access decoded JSON data (from API) outside the URLSession data task Function Scope
Can't access decoded JSON data (from API) outside the URLSession data task Function Scope

Time:10-31

I am facing an issue when trying to retrieve and decode JSON data from an API. I am able to get the data from the API and decode it successfully, but I can't access it from outside the function scope. I am using the following function to get and decode data. The API returns an array of JSON objects.

func getJSON(completed: @escaping () -> ()) {
        
        var jsonData = [API_data] () // A struct for retrieved data
        
        let url = "URL Here" // I have the original URL here, which I can't share

        let task = URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: { [self]data,response,error in
            
            guard let data = data, error == nil else{
                print("error")
                return
            }
            
            do{
            
                jsonData = try JSONDecoder().decode([API_data].self,from:data)
                
            } catch{
                print(error)
            }
        
            
            print(jsonData[0].id) // This prints my data
            
        })
        
        print(jsonData[0].id) // This won't print my data

        
        task.resume()
        
    }
struct API_data: Codable {
    let id : String
}

As a result of this, I cannot use this data anywhere in the application. Any help will be appreciated. I have also tried making jsonData a global variable, updating it in the function and returning it and then using it, still doesn't work.

Thanks for your help.

CodePudding user response:

As you already have a completion handler use it and pass the received data

func getJSON(completed: @escaping ([API_data]) -> Void) {
    
    let url = "URL Here" // I have the original URL here, which I can't shar
    let task = URLSession.shared.dataTask(with: URL(string: url)!) { data, _ , error in
        
        if let error = error { print(error); return }
        
        do {
            completed(try JSONDecoder().decode([API_data].self,from:data!))
        } catch{
            print(error)
        }
    }
    task.resume()
}

and use it

getJSON { apiData in 
    print(apiData[0].id) // This prints my data
}

Or more comfortable with the Result type

func getJSON(completed: @escaping (Result<[API_data],Error>) -> Void) {
    
    let url = "URL Here" // I have the original URL here, which I can't shar
    let task = URLSession.shared.dataTask(with: URL(string: url)!) { data, _ , error in
        
        if let error = error { completed(.failure(error)); return }
        Result { try JSONDecoder().decode([API_data].self,from: data!) }
    }
    task.resume()
}


getJSON { result in 
    switch result {
        case .success(let apiData): print(apiData[0].id) // This prints my data
        case .failure(let error): print(error)
    }
    
}

CodePudding user response:

It is asynchronous, you might want to access it a bit later when it’s ready, e.g. by using the completion handler.

CodePudding user response:

Try creating a completion handler from your API function and send the data with the completion. And try using it there.

  • Related