Swift 闭包:无法将类型“()”的 return 表达式转换为 return 类型 'LiveSearchResponse?'
Swift Closures: Cannot convert return expression of type '()' to return type 'LiveSearchResponse?'
我有两个控制器。
Maincontroller
Dropdown
Maincontroller
允许用户打开下拉菜单。
Dropdown
允许用户 select 列表中的一行。 selected 行值将传递给 Maincontroller
。在 Dropdown
控制器中有 searchBar。当用户搜索某些内容时,它会要求 Maincontroller
获取搜索查询的数据。 Maincontroller
将从 Web API 和 return 结果中获取数据到 Dropdown
。
我在使用闭包 return 将数据从 Maincontroller
传输到 Dropdown
时遇到了问题。
我从 Maincontroller
模态地呈现 Dropdown
,如下所示。
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)
以下是我在 Maincontroller
中从 Web API 获取搜索数据的函数。它 return 类型为 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)
}
}
当我从闭包中 returning 对象时,下面的块出现编译时错误。
Cannot convert return expression of type '()' to return type 'LiveSearchResponse?'
search: { (query, spaging) -> LiveSearchResponse? in
let res = self.fetchPatients(query: query, forPaging: spaging, response: { (response) in
})
return res
我不知道如何在从异步函数获取数据后 return 将值赋给闭包。
编辑 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 {
}
}
你能建议我存档目标的正确方法吗?
如果你正在调用异步方法,那么 search
不应该 return,你应该传递一个完成块,我认为它看起来像这样:
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 {
}
}
我有两个控制器。
Maincontroller
Dropdown
Maincontroller
允许用户打开下拉菜单。
Dropdown
允许用户 select 列表中的一行。 selected 行值将传递给 Maincontroller
。在 Dropdown
控制器中有 searchBar。当用户搜索某些内容时,它会要求 Maincontroller
获取搜索查询的数据。 Maincontroller
将从 Web API 和 return 结果中获取数据到 Dropdown
。
我在使用闭包 return 将数据从 Maincontroller
传输到 Dropdown
时遇到了问题。
我从 Maincontroller
模态地呈现 Dropdown
,如下所示。
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)
以下是我在 Maincontroller
中从 Web API 获取搜索数据的函数。它 return 类型为 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)
}
}
当我从闭包中 returning 对象时,下面的块出现编译时错误。
Cannot convert return expression of type '()' to return type 'LiveSearchResponse?'
search: { (query, spaging) -> LiveSearchResponse? in
let res = self.fetchPatients(query: query, forPaging: spaging, response: { (response) in
})
return res
我不知道如何在从异步函数获取数据后 return 将值赋给闭包。
编辑 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 {
}
}
你能建议我存档目标的正确方法吗?
如果你正在调用异步方法,那么 search
不应该 return,你应该传递一个完成块,我认为它看起来像这样:
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 {
}
}