konya
konya

Reputation: 161

Introduce background async thread

I want to run the exportExcel() in the background thread -DispatchQueue.global().async- but I could not able to achieve it. Any help would be appreciated.

override func viewDidLoad() {
  super.viewDidLoad()
  setTableView()
  dataExport()
}

private func dataExport() {
  dataExport { [weak self] (res) in
    switch res {
    case .failure (let error):
      print(error)
    case .success(let data):
      print("success")
    }
  }
}
  
private func dataExport(completion: @escaping(result)) {
   do {
    let data = try classVM.exportExcel()
    completion(.success(data))
   } catch { completion(.failure(error)) }
}
  

ClassViewModel.swift

func exportExcel() throws -> [[String]] {
    guard let path = Bundle.main.path(forResource: name, ofType: type ) else { throw error }
    do {
      return try readData(filePath: path)
    } catch {
      throw error
    }
}

Upvotes: 0

Views: 81

Answers (1)

Rob
Rob

Reputation: 437392

If you want to make this synchronous method to behave asynchronously, just

  • dispatch the code to a background queue

  • when it is complete, call an @escaping completion handler closure so the caller knows when it is done.

E.g.

func exportExcel(completion: @escaping (Result<[[String]], Error>) -> Void) {
    DispatchQueue.global().async {
        do {
            guard let path = Bundle.main.path(forResource: name, ofType: type) else { throw ExportError.invalidPath }
            let result = try readData(filePath: path) 
            completion(.success(result))
        } catch {
            completion(.failure(error))
        }
    }
}

By the way, I wasn’t sure what you make of your throw error, so I created an error for that, e.g.

enum ExportError: Error {
    case invalidPath
}

By the way, often, people would dispatch the result back to the main queue:

func exportExcel(completion: @escaping (Result<[[String]], Error>) -> Void) {
    DispatchQueue.global().async {
        do {
            guard let path = Bundle.main.path(forResource: name, ofType: type) else { throw ExportError.invalidPath }
            let result = try readData(filePath: path) 
            DispatchQueue.main.async {
                completion(.success(result))
            }
        } catch {
            DispatchQueue.main.async {
                completion(.failure(error))
            }
        }
    }
}

And when you want to call it:

exportExcel { [weak self] result in
    switch result {
    case .failure(let error):
        print(error)
    case .success(let data):
        print("success")
    }
}

Upvotes: 1

Related Questions