Обработчик завершения выполняется до завершения запроса - PullRequest
0 голосов
/ 06 июля 2019

У меня есть приложение, которое использует UIImagePickerController для выбора изображения. Это изображение затем передается в функцию API. Как только эта функция завершена, я передаю результат с помощью делегата модально отображаемому контроллеру с результатами. Однако, модальный контроллер представлен перед блоком завершения, и мои сообщения об ошибках AlerViewController никогда не вызываются.

API запускается в фоновом потоке, я установил завершение в основном потоке (поскольку он обновляет пользовательский интерфейс - представляет модальный контроллер), но он вызывается до того, как завершение полностью выполнено.

Код ниже;

Запрос API

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)
            }
        }
    }

В запросе API все мои AlertViewController функции вызываются в главном потоке и затем возвращаются из запроса. Блок успеха также вызывается в главном потоке.

Что я здесь не так делаю? ...

Обновление

Я не совсем уверен, почему это работает, но он делает все, что мне нужно. Я переместил запрос API в другую функцию за пределами

var selectedImage: UIImage? {
        didSet {

в моем контроллере.

Новый рабочий код

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)
            }
        }
    }

1 Ответ

1 голос
/ 06 июля 2019

Я думаю, вы хотите этого.

    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)
                    }
                }
            }
        }
    }
...