Быстрые замыкания: не удается преобразовать возвращаемое выражение типа '()' в возвращаемый тип 'LiveSearchResponse?' - PullRequest
0 голосов
/ 05 апреля 2019

У меня два контроллера.

  1. Maincontroller
  2. Dropdown

Maincontroller позволяет пользователям открывать выпадающий список.Dropdown позволяет пользователям выбирать строку из списка.значение выбранной строки будет передано MaincontrollerDropdown контроллере есть панель поиска.Когда пользователь что-то ищет, он просит Maincontroller получить данные для поискового запроса.Maincontroller будет извлекать данные из Web API и возвращать результат в Dropdown.

Я столкнулся с проблемой при возврате данных из Maincontroller в Dropdown с использованием замыкания.

я представляю Dropdown модально из Maincontroller, как показано ниже.

            let searchVC = LiveSearchDropDown<DropDownTitleTCell>.init(configureCell: { (cell ,object) -> DropDownTitleTCell in

                cell.lblTitle.text = "Dummy"
                return cell


        }, selection: { (selectedObject) in

            print(selectedObject)
            self.dismiss(animated: false, completion: nil)
        }, search: { (query, spaging) -> LiveSearchResponse? in

            let res  = self.fetchPatients(query: query, forPaging: spaging, response: { (response) in

            })
            return res

        })
        self.present(searchVC, animated: true)

Ниже приводится функция, в которой я получаю данные поиска из Web API в Maincontroller.Возвращает объект типа LiveSearchResponse.

    func fetchPatients(query searchText: String, forPaging : Paging, response: @escaping(LiveSearchResponse) -> ()) {

    let params = Prefs.getAPICallParameters()
    var responseData = LiveSearchResponse()

    APIManager.shared.jsonRequest(url: AppConstant.Patient.getPatientList, parameters: params, method: .post, encoding: JSONEncoding.default, onSuccess: { (resposeJSON) in
        if let patientList = resposeJSON["data"].array {


            if patientList.count > 0 {
                var data = [Patient]()

                //success retreived
                for patient in patientList {
                    data.append(Patient(json: patient))
                }

                if patientList.count < 20 {
                    forPaging.shouldLoadMore = false
                } else {
                    forPaging.shouldLoadMore = true
                }
                responseData.data = data
                responseData.error = nil

            } else {
                forPaging.status = .failed
            }
            response(responseData)

        } else {
            forPaging.status = .failed
            self.presentAlertWithTitle(title: "Error", message: "AppConstant.Patient.getPatientList data Key not found", options: "Ok", completion: { (option) in
            })
            response(responseData)
        }
    }) { (error) in
        forPaging.status = .failed
        self.presentAlertWithTitle(title: "Error", message: error.message, options: "Ok", completion: { (option) in
        })
        response(responseData)
    }
}

Я получаю ошибку времени компиляции в блоке ниже, когда возвращаю объект из замыкания.

Невозможно преобразовать возвращаемое выражение типа '()' в возвращаемый тип 'LiveSearchResponse?'

search: { (query, spaging) -> LiveSearchResponse? in

            let res  = self.fetchPatients(query: query, forPaging: spaging, response: { (response) in

            })
            return res

Я не знаю, как вернуть значение в Closures послеизвлечение данных из асинхронной функции.

РЕДАКТИРОВАТЬ 2

В Dropdown я объявил как

public let searchQuery: LiveSearchQuery
typealias LiveSearchQuery = (String, Paging) -> LiveSearchResponse?

Инициализация

required init(configureCell: @escaping CellConfiguration, selection: @escaping Selection, search: @escaping LiveSearchQuery) {
    self.configureCell = configureCell
    self.selection = selection
    self.searchQuery = search
    super.init(nibName: nil, bundle: nil)
    self.modalPresentationStyle = .formSheet
    self.modalTransitionStyle = .crossDissolve
    self.preferredContentSize = CGSize(width: 400, height: 400)
}

и Вызовэто как

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
    if let query = searchBar.text, !query.isEmpty {
        self.paging.status = .loading
        self.tableView.reloadData()
        let response = searchQuery(query, self.paging)
        if response?.error == nil {
            self.dataModels = response?.data as? [AnyObject]
        } else {
        }
        self.tableView.reloadData()
        searchBar.resignFirstResponder()
    } else {

    }
}

Можете ли вы предложить мне правильный способ архивирования цели?

1 Ответ

2 голосов
/ 05 апреля 2019

Если вы вызываете асинхронный метод, то search не должен возвращаться, вы должны передать блок завершения, он будет выглядеть примерно так, я думаю:

search: {[weak self] (query, spaging, completion) in

    self?.fetchPatients(query: query, forPaging: spaging, response: { (response) in
        completion(response)
    })

Редактировать 1

У меня есть немного больше идей с добавленной информацией, вы должны быть в состоянии сделать что-то вроде этого:

public let searchQuery: LiveSearchQuery
typealias LiveSearchQuery = (String, Paging, @escaping (LiveSearchResponse?)->())->()

required init(configureCell: @escaping CellConfiguration, selection: @escaping Selection, search: @escaping LiveSearchQuery) {
    self.configureCell = configureCell
    self.selection = selection
    self.searchQuery = search
    super.init(nibName: nil, bundle: nil)
    self.modalPresentationStyle = .formSheet
    self.modalTransitionStyle = .crossDissolve
    self.preferredContentSize = CGSize(width: 400, height: 400)
}

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
    if let query = searchBar.text, !query.isEmpty {
        self.paging.status = .loading
        self.tableView.reloadData()
        searchQuery(query, self.paging) { [weak self] response in
            DispatchQueue.main.async {
                if response?.error == nil {
                    self?.dataModels = response?.data as? [AnyObject]
                } else {
                }
                self?.tableView.reloadData()
                searchBar.resignFirstResponder()
            }
        }
    } else {

    }
}
...