Skip to content

Instantly share code, notes, and snippets.

@TaLinh
Created May 13, 2022 09:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TaLinh/c68ea866cc6246e1b706cc0700c3f6be to your computer and use it in GitHub Desktop.
Save TaLinh/c68ea866cc6246e1b706cc0700c3f6be to your computer and use it in GitHub Desktop.
class WeakObject<T: AnyObject>: Hashable {
private(set) weak var object: T?
let identifier: ObjectIdentifier
static func == (lhs: WeakObject<T>, rhs: WeakObject<T>) -> Bool {
return lhs.identifier == rhs.identifier
}
func hash(into hasher: inout Hasher) {
hasher.combine(identifier)
}
init(object: T) {
self.object = object
self.identifier = ObjectIdentifier(object)
}
}
class WeakDelegateCollection<T> {
typealias Canceller = () -> Void
private var objects: Set<WeakObject<AnyObject>> = []
@discardableResult
func add(_ delegate: T) -> Canceller {
//WeakObject chỉ hoạt động với reference type
guard type(of: delegate as Any) is AnyClass else {
fatalError("Class misused: WeakDelegateCollection should only be use with class")
}
//Chủ động cast delegate to be AnyObject bởi swift đang nhận diện delegate thuộc type T - vừa có thể là class vừa có thể là struct
//Sau khi cast ta có thể dùng [weak delegate] để tránh retain cycle trong Canceller
let delegate = delegate as AnyObject
let object = WeakObject(object: delegate)
objects.insert(object)
//Sau khi gọi add có thể lưu lại Canceller để chủ động huỷ đăng ký
return { [weak self, weak delegate] in
guard let self = self, let delegate = delegate as? T else { return }
self.remove(delegate)
}
}
func trigger(_ action: (T) -> Void) {
for weakObject in objects {
//Nếu object trong WeakObject chưa deinit => chạy closure
if let object = weakObject.object as? T {
action(object)
} else {
//Xoá WeakObject có object đã được deinit
objects.remove(weakObject)
}
}
}
func remove(_ delegate: T) {
guard type(of: delegate as Any) is AnyClass else { return }
objects.remove(WeakObject(object: delegate as AnyObject))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment