Search code examples
iosswiftsegueuistoryboardsegue

Performing an automatic segue


I'm downloading remote JSON data and want my loading screen to stay up until the download is complete. Once my parse method finishes running, a segue should be called to move to the next view automatically.

I've verified that my data is properly downloading and parsing. My performSegue function is even being called when I throw up a breakpoint. But the application is still not moving to the next view.

Here's where I'm calling my parse method and then immediately calling the desired segue:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    downloadSources(atURL: "https://newsapi.org/v1/sources?language=en")
    performSegue(withIdentifier: "loadingFinished", sender: self)
}

For reference, if you need it, here is my parse method in its entirety:

func downloadSources(atURL urlString: String) {
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)

    if let validURL = URL(string: urlString) {
        var request = URLRequest(url: validURL)
        request.setValue("49fcb8e0fa604e7aa461ee4f22124177", forHTTPHeaderField: "X-Api-Key")
        request.httpMethod = "GET"

        let task = session.dataTask(with: request) { (data, response, error) in
            if error != nil {
                assertionFailure()
                return
            }

            guard let response = response as? HTTPURLResponse,
            response.statusCode == 200,
            let data = data

                else {
                    assertionFailure()
                    return
            }

            do {
                if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
                    guard let sources = json["sources"] as? [[String: Any]]

                        else {
                            assertionFailure()
                            return
                    }

                    for source in sources {
                        guard let id = source["id"] as? String,
                        let name = source["name"] as? String,
                        let description = source["description"] as? String

                            else {
                                assertionFailure()
                                return
                        }

                        self.sources.append(Source(id: id, name: name, description: description))
                    }
                }
            }

            catch {
                print(error.localizedDescription)
                assertionFailure()
            }
        }

        task.resume()
    }
}

Thanks in advance.


Solution

  • Sounds like a closure callback is what you want.

    typealias CompletionHandler = ((_ success:Bool) -> Void)?
    
    override func viewDidLoad() {
        super.viewDidLoad()
            downloadSources(atURL: "www.example.com", completion: {
                if success {
                    performSegue(withIdentifier: "loadingFinished", sender: self)
                    return
                }
                // otherwise deal with failure
        })
    }
    
    func downloadSources(atURL urlString: String, completion: CompletionHandler) {
        if error != nil {
            completion?(false)
            return
        }
        // finish downlaod
        completion?(true)
    }