skip to Main Content

I am getting an error which seems to be more of that the request did not go through correctly. I say that because when I reload the app it works fine

The part of the code causing the error is:

 let post = try! JSONDecoder().decode(Post.self, from: data!)
             

the error is:

Fatal error: Unexpectedly found nil while unwrapping an Optional value

the full code:

func getShows(station:String,completion: @escaping ([Program]) -> ()) {
        guard let url = URL(string: "https://api.drn1.com.au/api-access/programs/(station)") else { return }
          
          URLSession.shared.dataTask(with: url) { (data, _, _) in
              // Based on the updated structs, you would no
              // longer be decoding an array
              let post = try! JSONDecoder().decode(Post.self, from: data!)
              DispatchQueue.main.async{
                  // The array is stored under programs now
                  completion(post.programs)
              }              
          }
      .resume()
      }

Is there away instead of crashing the app, it just tries to run again?

2

Answers


  1. (Answering your question in the last sentence)

    Yes, don’t force-unwrap "data", don’t force-resolve the "try". Doing either will result in a crash if either data is null (which, for network calls is a reasonable expectation), or if the JSONDecoder cannot parse the data correctly.

    How often you call this method is up to you (e.g., as soon as a view is loaded).

    `

          URLSession.shared.dataTask(with: url) { (data, response, error) in
              guard let actualData = data, 
                    let urlResponse = response as? URLResponse,
                    urlResponse.status == 200 //or whatever
                    else { return } 
    
    
              if let post = try? JSONDecoder().decode(Post.self, from:actualData){
                  completion(post.programs)  
              }         
          }
      .resume()
      }`
    
    Login or Signup to reply.
  2. If your app is for iOS 13+, and you can use Combine, then your method could be rewritten like this

    /// add this var somewhere in your class
    var subscriptions: Set<AnyCancellable> = .init()
    
    func getShows(station: String, retries: Int = 3, completion: @escaping ([Program]) -> Void) {
        guard let url = URL(string: "https://api.drn1.com.au/api-access/programs/(station)") else { return }
    
        let result = URLSession.shared.dataTaskPublisher(for: url)
            .map { $0.0 }
            .decode(type: Post.self, decoder: JSONDecoder())
            .retry(retries)
    
        result.sink { _ in } receiveValue: { post in
            completion(post.programs)
        }
        .store(in: &subscriptions)
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search