Files
featherVoice/TUIKit/TUICallKit/TUICallKit-Swift/Utils/Observers.swift

88 lines
2.6 KiB
Swift
Raw Normal View History

2025-08-08 10:49:36 +08:00
//
// Observers.swift
// TUICallKit
//
// Created by vincepzhang on 2023/4/3.
//
import Foundation
class Observer {}
public class Observable<Type> {
// MARK: - Callback
fileprivate class Callback {
fileprivate weak var observer: AnyObject?
fileprivate let options: [ObservableOptions]
fileprivate let closure: (Type, ObservableOptions) -> Void
fileprivate init(
observer: AnyObject,
options: [ObservableOptions],
closure: @escaping (Type, ObservableOptions) -> Void) {
self.observer = observer
self.options = options
self.closure = closure
}
}
// MARK: - Properties Use Swift's didSet feature to call back the value to the callback
public var value: Type {
didSet {
removeNilObserverCallbacks()
notifyCallbacks(value: oldValue, option: .old)
notifyCallbacks(value: value, option: .new)
}
}
private func removeNilObserverCallbacks() {
callbacks = callbacks.filter { $0.observer != nil }
}
// MARK: Callback to callback to implement closure callback
private func notifyCallbacks(value: Type, option: ObservableOptions) {
let callbacksToNotify = callbacks.filter { $0.options.contains(option) }
callbacksToNotify.forEach { $0.closure(value, option) }
}
// MARK: - Object Lifecycle
public init(_ value: Type) {
self.value = value
}
// MARK: - Managing Observers
private var callbacks: [Callback] = []
public func addObserver(
_ observer: AnyObject,
removeIfExists: Bool = true,
options: [ObservableOptions] = [.new],
closure: @escaping (Type, ObservableOptions) -> Void) {
if removeIfExists {
removeObserver(observer)
}
let callback = Callback(observer: observer, options: options, closure: closure)
callbacks.append(callback)
if options.contains(.initial) {
closure(value, .initial)
}
}
public func removeObserver(_ observer: AnyObject) {
callbacks = callbacks.filter { $0.observer !== observer }
}
}
// MARK: - ObservableOptions
public struct ObservableOptions: OptionSet {
public static let initial = ObservableOptions(rawValue: 1 << 0)
public static let old = ObservableOptions(rawValue: 1 << 1)
public static let new = ObservableOptions(rawValue: 1 << 2)
public var rawValue: Int
public init(rawValue: Int) {
self.rawValue = rawValue
}
}