代码之家  ›  专栏  ›  技术社区  ›  Serj

当元素被明确约束时,为什么swift编译器在推断泛型元素的类型时抛出错误?

  •  3
  • Serj  · 技术社区  · 7 年前

    当我在实现一个保持对其元素弱引用的数组时,我一使用 Collection 扩展方法,在使用 收藏 方法正确、预期地编写代码。

    预期行为

    代码编译时应该没有错误。

    当前行为

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

    1. Weakref需要这个元素?是类类型
    2. 无法推断“items”的类型

    可能的解决方案

    我找到的唯一解决方案是将属性项公开,并使用for循环而不是 收藏 扩展方法。完成此操作后,编译器能够推断 items 甚至是 收藏 方法有效。

    复制的步骤

    首先实现 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) }
        }
    }
    

    第三,实施 收藏 扩展实现:

    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属性的实例,但不在同一个源文件中 维卡雷 例如:

    var objects: WeakArray<UIViewController> = WeakArray.init([])
    

    第五步和最后一步调用 收藏 协议,例如:

    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提出问题的标准。特别感谢Martinar指导我在StackOverflow上发布一个好问题。

    1 回复  |  直到 7 年前
        1
  •  2
  •   Martin R    7 年前

    Collection 有关联的 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)
        }
    }