arrays - 为什么当元素明显受到约束时,Swift 编译器在推断我的通用元素的类型时会抛出错误?
问题描述
当我在实现一个保持对其元素的弱引用的数组时,我在使用Collection
扩展方法的方法时偶然发现了一个编译错误,然后才使用该Collection
方法,代码编译正确且符合预期。
预期行为
代码应该编译没有错误。
当前行为
编译器抛出以下两个错误:
- WeakRef 需要那个元素?成为类类型
- 无法推断“项目”的类型
可能的解决方案
我找到的唯一解决方案是将属性项公开并使用 for 循环而不是Collection
扩展方法。在这样做之后,编译器能够推断出类型items
,甚至Collection
方法都有效。
重现步骤
首先实现WeakRef
类:
final class WeakRef<T: AnyObject> {
weak var value: T?
init(_ value: T) {
self.value = value
}
}
其次实现WeakArray
结构:
struct WeakArray<Element: AnyObject> {
public var items: [WeakRef<Element>] = []
init(_ elements: [Element]) {
items = elements.map { WeakRef($0) }
}
}
第三个实现Collection
扩展实现:
extension WeakArray: Collection {
var startIndex: Int { return items.startIndex }
var endIndex: Int { return items.endIndex }
subscript(_ index: Int) -> Element? {
return items[index].value
}
func index(after idx: Int) -> Int {
return items.index(after: idx)
}
}
第四,创建不在同一个源文件中的 WeakArray 属性的实例,WeakArray
例如:
var objects: WeakArray<UIViewController> = WeakArray.init([])
第五步也是最后一步调用Collection
协议的方法,例如:
objects.forEach({ $0?.view.backgroundColor = .white })
上下文(环境)
此代码无法在使用 Swift 4.1 的 Xcode 版本 9.3.1 (9E501) 上编译
附加说明
上述代码的解决方案在以下链接中找到:
- https://marcosantadev.com/swift-arrays-holding-elements-weak-references/
- https://www.objc.io/blog/2017/12/28/weak-arrays/
提前感谢您提供的任何帮助。这篇文章经过完全编辑,以符合 Stackoverflow 提出问题的标准。特别感谢 MartinR 指导我在 Stackoverflow 上发布一个好问题。
解决方案
ACollection
具有关联的Element
类型,这似乎与您的通用Element
占位符冲突。E
为占位符使用不同的名称可以解决问题:
struct WeakArray<E: AnyObject> {
public var items: [WeakRef<E>] = []
init(_ elements: [E]) {
items = elements.map { WeakRef($0) }
}
}
extension WeakArray: Collection {
var startIndex: Int { return items.startIndex }
var endIndex: Int { return items.endIndex }
subscript(_ index: Int) -> E? {
return items[index].value
}
func index(after idx: Int) -> Int {
return items.index(after: idx)
}
}
推荐阅读
- ansible - Ansible Jinja2 总是显示“已更改”
- makefile - 在 make 文件中忽略 c11 标志
- java - 覆盖应用于 RestTemplate 的 RestTemplateCustomizer
- python - 我不知道为什么我不断收到错误 'str' has not attribute 'message'
- javascript - 如何通过电子邮件发送购物车的结果?
- javascript - button.value 返回 "" 。预期 - 文本值
- bash - 向 shell 脚本中的选项提供参数列表的方法?
- angular - 如何更改 Angular 10 库构建结构
- javascript - Typescript 中的条件 super() 语句
- javascript - 如何在反应中呈现 HTMLCollection(作为道具传递)