首页 > 解决方案 > 为什么当元素明显受到约束时,Swift 编译器在推断我的通用元素的类型时会抛出错误?

问题描述

当我在实现一个保持对其元素的弱引用的数组时,我在使用Collection扩展方法的方法时偶然发现了一个编译错误,然后才使用该Collection方法,代码编译正确且符合预期。

预期行为

代码应该编译没有错误。

当前行为

编译器抛出以下两个错误:

  1. WeakRef 需要那个元素?成为类类型
  2. 无法推断“项目”的类型

可能的解决方案

我找到的唯一解决方案是将属性项公开并使用 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) 上编译

附加说明

上述代码的解决方案在以下链接中找到:

  1. https://marcosantadev.com/swift-arrays-holding-elements-weak-references/
  2. https://www.objc.io/blog/2017/12/28/weak-arrays/

提前感谢您提供的任何帮助。这篇文章经过完全编辑,以符合 Stackoverflow 提出问题的标准。特别感谢 MartinR 指导我在 Stackoverflow 上发布一个好问题。

标签: arraysswiftgenericscompiler-errors

解决方案


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)
    }
}

推荐阅读