在请求完成之前执行的完成处理程序

时间:2019-07-06 11:28:07

标签: swift grand-central-dispatch dispatch completionhandler

我有一个使用UIImagePickerController选择图像的应用。然后将该图像传递到API函数中。该功能完成后,我将使用委托将结果传递给显示结果的模式显示控制器。但是,模态控制器显示在完成框之前,并且永远不会调用我的错误AlerViewController警报。

该API在后台线程中运行,我已经在主线程上设置了完成功能(因为它会更新UI-显示模式控制器),但是会在完全执行完成之前调用它。

下面的代码;

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 个答案:

答案 0 :(得分:1)

我想你想要这个。

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