Skip to content

Instantly share code, notes, and snippets.

@codelynx
Last active July 22, 2018 19:33
Show Gist options
  • Select an option

  • Save codelynx/702e18623a4bfebb5a721c1703e5068f to your computer and use it in GitHub Desktop.

Select an option

Save codelynx/702e18623a4bfebb5a721c1703e5068f to your computer and use it in GitHub Desktop.
ZWeakSet that collection of hashable weak set of objects [swift 3.0]
//
// ZWeakSet.swift
// ZTableLayout
//
// The MIT License (MIT)
//
// Copyright (c) 2016 Electricwoods LLC, Kaz Yoshikawa.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import Foundation
private class ZWeakObject<T: AnyObject>: Hashable {
weak var object: T?
init(_ object: T) {
self.object = object
}
var hashValue: Int {
var hashValue = 0
if var object = object {
withUnsafePointer(to: &object, {
hashValue = $0.hashValue
})
}
return hashValue
}
}
private func == <T> (lhs: ZWeakObject<T>, rhs: ZWeakObject<T>) -> Bool {
return lhs.object === rhs.object
}
public struct ZWeakSet<T: AnyObject>: Sequence {
private var _objects: Set<ZWeakObject<T>>
public init() {
_objects = Set<ZWeakObject<T>>()
}
public init(_ objects: [T]) {
self._objects = Set<ZWeakObject<T>>(objects.map { ZWeakObject($0) })
}
public var objects: [T] {
return _objects.flatMap { $0.object }
}
public func contains(object: T) -> Bool {
return self._objects.contains(ZWeakObject(object))
}
public mutating func add(_ object: T) {
_objects.insert(ZWeakObject(object))
}
public mutating func add(_ objects: [T]) {
_objects.formUnion(objects.map { ZWeakObject($0) })
}
public mutating func remove(_ object: T) {
_objects.remove(ZWeakObject(object))
}
public mutating func remove(_ objects: [T]) {
_objects.subtract(objects.map { ZWeakObject($0) })
}
public func makeIterator() -> AnyIterator<T> {
let objects = self.objects
var index = 0
return AnyIterator {
defer { index += 1 }
return index < objects.count ? objects[index] : nil
}
}
}
@simonseyer
Copy link

I made the experience that the pointer in withUnsafePointer can change randomly. I now use a version backed by a NSHashTable: https://gist.github.com/simonseyer/cf73e733355501405982042f760d2a7d.

@zhubofei
Copy link

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

We should probably unwrap and compare, because nil === nil.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment