0

I'm coming from a JavaScript/Flutter environment and I need to await an asynchronous function in Swift. Is there a way to do it?

Basically, I want to return repoNames from a class but a "task" is executing way faster than a return keyword.

Here's the code:

import UIKit

class SearchViewModel {
    let textFieldText: String?
    var repoNames: Array<String> = []
    
    init(textFieldText: String?) {
        self.textFieldText = textFieldText
    }
    
    func searchForRepo() -> Array<String> {
        let baseUrl = "https://api.github.com/search/repositories?q="
        
        let finalUrl = URL(string: baseUrl + self.textFieldText!)
        
        let session = URLSession.shared
        
        let task = session.dataTask(with: finalUrl!) { (data, response, error) in
            guard let data = data else { return }
            
            let repos: Items = try! JSONDecoder().decode(Items.self, from: data)
            
            for repo in repos.items {
                self.repoNames.append(repo.name)
                print(self.repoNames)
            }
        }
        task.resume()
        return self.repoNames
    }
}
szakes1
  • 794
  • 3
  • 16
  • 35
  • [Async await](https://github.com/apple/swift-evolution/blob/main/proposals/0296-async-await.md) will be in the next release of Ssift (you can experiment with it by downloading the latest Swift Toolchain) - https://ohmyswift.com/blog/2020/12/25/experimenting-with-swift-async-and-await-pattern-using-xcode/. In the meanwhile you need to use one of the approaches from the duplicate. – Paulw11 Jan 26 '21 at 19:33

1 Answers1

1

Add a completion

func searchForRepo(completion:@escaping( [String] -> ())) ->  {
    let baseUrl = "https://api.github.com/search/repositories?q=" 
    let finalUrl = URL(string: baseUrl + self.textFieldText!) 
    URLSession.shared.dataTask(with: finalUrl!) { (data, response, error) in
        guard let data = data else { return } 
        do {
            let repos = try JSONDecoder().decode(Items.self, from: data)
            self.repoNames = repos.items.map { $0repo.name }  
            completion(self.repoNames)
         } 
         catch {
             print(error)
         } 
        
      }.resume()  
}

When calling

SearchViewModel(textFieldText:"someValue").searchForRepo { res in
  print(res)
}
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87