Reputation: 3036
I have an app that uses UIImagePickerController
to select an image. That image is then passed into an API function. Once that function is complete I pass the result using a delegate to a modal displayed controller with the results. However, the modal controller is presented before the completion block and my error AlerViewController
alerts are never called.
The API is run in the background thread, I have set the completion on the main thread (as it updates the UI - presents the modal controller) but it gets called before the completion is fully executed.
Code below;
func searchImage(with image: UIImage, to viewController: UIViewController, success: @escaping([ViImageResult]?) -> Void) {
var results = [ViImageResult]()
let params = ViUploadSearchParams(image: image)
ViSearch.sharedInstance.uploadSearch(params: params, successHandler: { (data : ViResponseData?) -> Void in
guard let data = data else { return }
if data.result.isEmpty {
AlertViewController.noResultsFound(viewController: viewController)
return
} else {
if data.hasError {
AlertViewController.dataError(viewController: viewController)
return
} else {
for response in data.result {
results.append(response)
}
DispatchQueue.main.async {
success(results)
}
}
}
}, failureHandler: {
(error) -> Void in
AlertViewController.dataError(viewController: viewController)
})
}
var selectedImage: UIImage? {
didSet {
guard let selectedImage = selectedImage else { return }
ViSearchSDKService.shared.searchImage(with: selectedImage, to: self) { (results) in
guard let results = results else { return }
if self.resultsDelegate != nil {
self.resultsDelegate?.recievedResults(recievedResults: results)
}
}
let resultsController = ResultsViewController()
self.resultsDelegate = resultsController
let navigationController = UINavigationController(rootViewController: resultsController)
navigationController.modalPresentationStyle = .overFullScreen
DispatchQueue.main.async {
self.present(navigationController, animated: true, completion: nil)
}
}
}
In the API Request, all my AlertViewController
functions are called on the main thread and then returns out of the request. Success block is also called on the main thread.
What am I doing wrong here?...
I am not quite sure why this works but it does everything I need. I have moved the API Request into another function outside of
var selectedImage: UIImage? {
didSet {
in my controller.
var selectedImage: UIImage? {
didSet {
guard let selectedImage = selectedImage else { return }
self.searchImage(with: selectedImage)
}
}
func searchImage(with image: UIImage) {
ViSearchSDKService.shared.searchImage(with: image, to: self) { (results) in
guard let results = results else { return }
let resultsController = ResultsViewController()
self.resultsDelegate = resultsController
if self.resultsDelegate != nil {
self.resultsDelegate?.recievedResults(recievedResults: results)
}
let navigationController = UINavigationController(rootViewController: resultsController)
navigationController.modalPresentationStyle = .fullScreen
DispatchQueue.main.async {
self.present(navigationController, animated: true, completion: nil)
}
}
}
Upvotes: 0
Views: 131
Reputation: 1871
I think you want this.
var selectedImage: UIImage? {
didSet {
// make sure it was not set to nil
guard let selectedImage = selectedImage else { return }
// set up your view controller for the response
let resultsController = ResultsViewController()
self.resultsDelegate = resultsController
let navigationController = UINavigationController(rootViewController: resultsController)
// do your search
ViSearchSDKService.shared.searchImage(with: selectedImage, to: self) { (results) in
// leave no path without visible side-effect
guard let results = results else { debugPrint("nil results"); return }
// now that we have the result, present your results view controller
navigationController.modalPresentationStyle = .overFullScreen
DispatchQueue.main.async {
self.present(navigationController, animated: true) { in
// once done presenting, let it know about the results
self.resultsDelegate?.recievedResults(recievedResults: results)
}
}
}
}
}
Upvotes: 1