在 swift 中的异步调用中使用参数
Using parameters on async call in swift
我正在与完成处理程序进行异步调用,该处理程序通过查询为我获取数据。这些查询可能因用户操作而异。
我的数据调用是这样的;
class DataManager {
func requestVideoData(query: QueryOn<VideoModel>, completion: @escaping (([VideoModel]?, UInt?, Error?) -> Void)) {
client.fetchMappedEntries(matching: query) { (result: Result<MappedArrayResponse<FRVideoModel>>) in
completion(videos, arrayLenght, nil)
}
}
}
我的 ViewController 看起来像这样;
DataManager().requestVideoData(query: /*One of the queries below*/) { videos, arrayLength, error in
//Use the data fetched based on the query that has been entered
}
我的查询是这样的;
let latestVideosQuery = QueryOn<FRVideoModel>().limit(to: 50)
try! latestVideosQuery.order(by: Ordering(sys: .createdAt, inReverse: true))
还有这个;
let countryQuery = QueryOn<FRVideoModel>()
.where(valueAtKeyPath: "fields.country.sys.contentType.sys.id", .equals("country"))
.where(valueAtKeyPath: "fields.country.fields.countryTitle", .includes(["France"]))
.limit(to: 50)
但我不完全确定如何以正确的方式实现这些查询,以便它们与 MVC 模型相对应。
我正在考虑 DataManager class 中的 switch 语句,并将一个值传递到我的 ViewController 上的查询参数中,这将导致对 fetchMappedEntries() 的正确调用。唯一的问题是我仍然需要根据我在 VC 中的查询执行正确的功能,所以我也需要一个 switch 语句。
或者我是否需要在 ViewController 中包含所有查询?我认为这是不正确的,因为它似乎应该出现在我的模型中。
这有点主观。我认为您希望将查询的构造放在 DataManager
而不是视图控制器中是正确的。
一种方法是简化请求接口,以便视图控制器只需要传递一个简单的请求,比如:
struct QueryParams {
let limit: Int?
let country: String?
}
然后您需要更改您的 DataManager
查询函数以改为使用此函数:
func requestVideoData(query: QueryParams, completion: @escaping (([VideoModel]?, UInt?, Error?) -> Void))
同样,这是主观的,因此您必须做出权衡。简化界面限制了它的灵活性,但它也简化了视图控制器必须知道的内容。
最后,我使用了一个稍微修改过的网络层和一个路由器,其中查询存储在 public 枚举中,然后我可以在 ViewController 中的函数中使用它。看起来像这样;
public enum Api {
case latestVideos(limit: UInt)
case countryVideos(countries: [String], limit: UInt)
}
extension Api:Query {
var query: QueryOn<VideoModel> {
switch self {
case .latestVideos(let limit):
let latestVideosQuery = QueryOn<VideoModel>().limit(to: limit)
try! latestVideosQuery.order(by: Ordering(sys: .createdAt, inReverse: true))
return latestVideosQuery
case .countryVideos(let countries, let limit):
let countryQuery = QueryOn<VideoModel>()
.where(valueAtKeyPath: "fields.country.sys.contentType.sys.id", .equals("country"))
.where(valueAtKeyPath: "fields.country.fields.countryTitle", .includes(countries))
.limit(to: limit)
return countryQuery
}
}
}
以及用于获取数据的 NetworkManager 结构;
struct NetworkManager {
private let router = Router<Api>()
func fetchLatestVideos(limit: UInt, completion: @escaping(_ videos: [VideoModel]?, _ arrayLength: UInt?,_ error: Error?) -> Void) {
router.requestVideoData(.latestVideos(limit: limit)) { (videos, arrayLength, error) in
if error != nil {
completion(nil, nil, error)
} else {
completion(videos, arrayLength, nil)
}
}
}
}
我正在与完成处理程序进行异步调用,该处理程序通过查询为我获取数据。这些查询可能因用户操作而异。
我的数据调用是这样的;
class DataManager {
func requestVideoData(query: QueryOn<VideoModel>, completion: @escaping (([VideoModel]?, UInt?, Error?) -> Void)) {
client.fetchMappedEntries(matching: query) { (result: Result<MappedArrayResponse<FRVideoModel>>) in
completion(videos, arrayLenght, nil)
}
}
}
我的 ViewController 看起来像这样;
DataManager().requestVideoData(query: /*One of the queries below*/) { videos, arrayLength, error in
//Use the data fetched based on the query that has been entered
}
我的查询是这样的;
let latestVideosQuery = QueryOn<FRVideoModel>().limit(to: 50)
try! latestVideosQuery.order(by: Ordering(sys: .createdAt, inReverse: true))
还有这个;
let countryQuery = QueryOn<FRVideoModel>()
.where(valueAtKeyPath: "fields.country.sys.contentType.sys.id", .equals("country"))
.where(valueAtKeyPath: "fields.country.fields.countryTitle", .includes(["France"]))
.limit(to: 50)
但我不完全确定如何以正确的方式实现这些查询,以便它们与 MVC 模型相对应。
我正在考虑 DataManager class 中的 switch 语句,并将一个值传递到我的 ViewController 上的查询参数中,这将导致对 fetchMappedEntries() 的正确调用。唯一的问题是我仍然需要根据我在 VC 中的查询执行正确的功能,所以我也需要一个 switch 语句。
或者我是否需要在 ViewController 中包含所有查询?我认为这是不正确的,因为它似乎应该出现在我的模型中。
这有点主观。我认为您希望将查询的构造放在 DataManager
而不是视图控制器中是正确的。
一种方法是简化请求接口,以便视图控制器只需要传递一个简单的请求,比如:
struct QueryParams {
let limit: Int?
let country: String?
}
然后您需要更改您的 DataManager
查询函数以改为使用此函数:
func requestVideoData(query: QueryParams, completion: @escaping (([VideoModel]?, UInt?, Error?) -> Void))
同样,这是主观的,因此您必须做出权衡。简化界面限制了它的灵活性,但它也简化了视图控制器必须知道的内容。
最后,我使用了一个稍微修改过的网络层和一个路由器,其中查询存储在 public 枚举中,然后我可以在 ViewController 中的函数中使用它。看起来像这样;
public enum Api {
case latestVideos(limit: UInt)
case countryVideos(countries: [String], limit: UInt)
}
extension Api:Query {
var query: QueryOn<VideoModel> {
switch self {
case .latestVideos(let limit):
let latestVideosQuery = QueryOn<VideoModel>().limit(to: limit)
try! latestVideosQuery.order(by: Ordering(sys: .createdAt, inReverse: true))
return latestVideosQuery
case .countryVideos(let countries, let limit):
let countryQuery = QueryOn<VideoModel>()
.where(valueAtKeyPath: "fields.country.sys.contentType.sys.id", .equals("country"))
.where(valueAtKeyPath: "fields.country.fields.countryTitle", .includes(countries))
.limit(to: limit)
return countryQuery
}
}
}
以及用于获取数据的 NetworkManager 结构;
struct NetworkManager {
private let router = Router<Api>()
func fetchLatestVideos(limit: UInt, completion: @escaping(_ videos: [VideoModel]?, _ arrayLength: UInt?,_ error: Error?) -> Void) {
router.requestVideoData(.latestVideos(limit: limit)) { (videos, arrayLength, error) in
if error != nil {
completion(nil, nil, error)
} else {
completion(videos, arrayLength, nil)
}
}
}
}