- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我已经构建了一个通用存储库,它返回我请求的资源。这工作得很好,直到我尝试通过将多个 fetch 调用包装到 DispatchGroup 中来执行分组请求。存储库是一个通用类,指示返回类型。
我将每个单独提取的响应存储到字典中,一旦所有这些都准备好,我就会将字典转换为预期的返回类型。
当泛型的类型为 [Something](即 T == [Something])时,就会出现问题
public typealias RepoCompletion<T: Codable> = (Result<T?, Error>) -> Void
public func fetch<T: Entity>(_ resources: [FetchResource<T>], completion: @escaping RepoCompletion<T>) {
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
let group = DispatchGroup()
let valueSyncQueue = DispatchQueue(label: "Repo.ValueSync")
var values = [String: T]()
for resource in resources {
group.enter()
self.localDataSource.fetch(resource) { result in
switch result {
case .success(let value):
if let value = value {
valueSyncQueue.sync {
values[resource.description] = value
}
}
case .failure(_): break
}
group.leave()
}
}
group.wait(timeout: .now() + 10)
let flattenedValues = resources.compactMap({ values[$0.description] }).flatMap({ $0 })
completion(.success(flattenedValues))
}
}
上面的代码无法编译。错误显示 Member 'success' in 'Result<_?, Error>' produces result of type 'Result<Success, Failure>', but context expects 'Result<_?, Error>'
.我认为问题的出现是因为泛型类型是 [] 并且编译器需要帮助。
调试时查看类型:
(lldb) po type(of: resources.compactMap({ values[$0.description] }))
Swift.Array<Swift.Array<Schedule>>
(lldb) po type(of: resources.compactMap({ values[$0.description] }).flatMap({ $0 }))
Swift.Array<Schedule>
(lldb) po type(of: flattenedValues)
Swift.Array<Swift.Array<Schedule>>
我不明白为什么表达 let flattenedValues = resources.compactMap({ values[$0.description] }).flatMap({ $0 })
一旦评估,左侧和右侧就有不同的类型:S
假设 T == [时间表]。我预计values
为[字符串:[时间表]]。那么当 .compactMap
我期望 [[Schedules]] 的结果,最后是 .flatMap
返回[时间表](即T)。但我遗漏了一些东西或者我不明白。
如果我尝试帮助编译器并强制将 flattenedValues 转换为! T,返回时崩溃了
Could not cast value of type 'Swift.Array' (0x1058073b0) to 'Schedule' (0x1044ac928). 2019-10-17 09:48:14.585362+0200 Chicisimo[86448:2426001] Could not cast value of type 'Swift.Array' (0x1058073b0) to 'Schedule' (0x1044ac928).
我不太明白,因为 T
类型为[Schedule]
且不是 Schedule
类型.
任何帮助将不胜感激!谢谢!
最佳答案
您收到此错误是因为您正在尝试创建 Result
数组为T
,当您完成时,期望出现一个 T
值。
values: [String: T]
建立一个列表 T
在你的 for 循环中:
for resource in resources {
// here value is a T
values[resource.description] = value
}
扁平值变量是 values
的紧凑映射的结果字典
let flattenedValues = resources.compactMap({ values[$0.description] }).flatMap({ $0 })
这意味着此时 flattenedValues
的类型是 [T]
.
完成 ( (Result<T?, Error>) -> Void
) 期望 Result
具有 T
类型的单个值,但您正在尝试使用数组( [T]
)来解决它。这就是您收到此错误的原因。
解决方案:
据我了解,您希望从多个资源( FetchResource
)获取实体,这意味着您可能希望始终返回实体数组( [T]
)。
如果是这样,您只需更改您的 RepoCompletion
到数组:[T]
。这看起来像这样:
// change RepoCompletion<T> to RepoCompletion<[T]>
public func fetch<T: Entity>(_ resources: [FetchResource<T>], completion: @escaping RepoCompletion<[T]>) {
// ...
}
关于ios - 转换作为数组的泛型类型时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58428281/
我是一名优秀的程序员,十分优秀!