我发现一些代码在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()方法。
最佳答案
这里的事情是我想要弱引用集。但是我找到了另一个解决方案。如果有人需要,这里是:
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) })
}
}