Created
May 13, 2022 09:08
-
-
Save TaLinh/c68ea866cc6246e1b706cc0700c3f6be to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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