由于类型未声明,如何将代码转换为Swift 4?

时间:2019-06-07 08:10:36

标签: swift xcode

我发现一些代码在Swift 4中不起作用。问题是未声明SequenceType和GeneratorOf,而且我不确定如何在Swift 4中使用新协议转换此代码。

我尝试将SequenceType更改为Sequence并将GeneratorOf更改为Iterator,但不确定其实际工作方式。


public struct WeakSet<T> where T: AnyObject, T: Hashable {
    typealias Element = T

    /// Maps Element hashValues to arrays of Entry objects.
    /// Invalid Entry instances are culled as a side effect of add() and remove()
    /// when they touch an object with the same hashValue.
    private var contents: [Int: [Entry<Element>]] = [:]

    public init(_ objects: T...) {
        self.init(objects)
    }

    public init(_ objects: [T]) {
        for object in objects {
            insert(newElement: object)
        }
    }

    /// Add an element to the set.
     mutating func insert(newElement: Element) {
        var entriesAtHash = validEntriesAtHash(hashValue: newElement.hashValue)
        var found = false
        for entry in entriesAtHash {
            if let existingElement = entry.element {
                if existingElement == newElement {
                    found = true
                    break
                }
            }
        }
        if found {
            return
        }
        let entry = Entry(element: newElement)
        entriesAtHash.append(entry)
        contents[newElement.hashValue] = entriesAtHash
    }

    /// Remove an element from the set.
     mutating func remove(removeElement: Element) {
        let entriesAtHash = validEntriesAtHash(hashValue: removeElement.hashValue)
        let entriesMinusElement = entriesAtHash.filter { $0.element != removeElement }
        if entriesMinusElement.isEmpty {
            contents[removeElement.hashValue] = nil
        }
        else {
            contents[removeElement.hashValue] = entriesMinusElement
        }
    }

    // Does the set contain this element?
     func contains(element: Element) -> Bool {
        let entriesAtHash = validEntriesAtHash(hashValue: element.hashValue)
        for entry in entriesAtHash {
            if entry.element == element {
                return true
            }
        }
        return false
    }

    private func validEntriesAtHash(hashValue: Int) -> [Entry<Element>] {
        if let entries = contents[hashValue] {
            return entries.filter {
                $0.element != nil
            }
        }
        else {
            return []
        }
    }
}

private struct Entry<T> where T: AnyObject, T: Hashable {
    typealias Element = T
    weak var element: Element?
}

// MARK: SequenceType
extension WeakSet: SequenceType {
    typealias Generator = GeneratorOf<T>

    /// Creates a generator for the items of the set.
    public func generate() -> Generator {
        // This is not straightforward because we need to iterate over the arrays and then their contents.
        var contentsGenerator = contents.values.enumerated()         // generates arrays of entities
        var entryGenerator = contentsGenerator.next()?.generate()  // generates entries
        return Swift.GeneratorOf {
            // Note: If entryGenerator is nil, the party is over. No more.
            if let element = entryGenerator?.next()?.element {
                return element
            }
            else { // Ran out of entities in this array. Get the next one, if there is one.
                entryGenerator = contentsGenerator.next()?.generate()
                return entryGenerator?.next()?.element
            }
        }
    }
}

因此,我遇到了SequenceType和GeneratorOf的未声明类型错误,而我却根本不了解底部的generate()方法。

1 个答案:

答案 0 :(得分:0)

这里的事情是我想要弱引用集。但是我找到了另一个解决方案。如果有人需要,这里是:

class WeakObject<T: AnyObject>: Equatable, Hashable {
    weak var object: T?
    init(object: T) {
        self.object = object
    }

    var hashValue: Int {
        if var object = object { return UnsafeMutablePointer<T>(&object).hashValue }
        return 0
    }

    static func == (lhs: WeakObject<T>, rhs: WeakObject<T>) -> Bool {
        return lhs.object === rhs.object
    }
}

class WeakObjectSet<T: AnyObject> {
    var objects: Set<WeakObject<T>>

    init() {
        self.objects = Set<WeakObject<T>>([])
    }

    init(objects: [T]) {
        self.objects = Set<WeakObject<T>>(objects.map { WeakObject(object: $0) })
    }

    var allObjects: [T] {
        return objects.compactMap { $0.object }
    }

    func contains(_ object: T) -> Bool {
        return self.objects.contains(WeakObject(object: object))
    }

    func addObject(_ object: T) {
        self.objects.formUnion([WeakObject(object: object)])
    }

    func addObjects(_ objects: [T]) {
        self.objects.formUnion(objects.map { WeakObject(object: $0) })
    }
}