Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>

This commit is contained in:
Matt Bruce 2025-02-06 21:31:09 -06:00
parent 58850aeb6e
commit a7d99fd523
7 changed files with 105 additions and 23 deletions

View File

@ -35,6 +35,7 @@ open class Control: UIControl, ViewProtocol, UserInfoable, Clickable {
// MARK: - Combine Properties
//--------------------------------------------------
open var subscribers = Set<AnyCancellable>()
open var subject = PassthroughSubject<Void, Never>()
open var onClickSubscriber: AnyCancellable?
@ -78,10 +79,19 @@ open class Control: UIControl, ViewProtocol, UserInfoable, Clickable {
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
/// When the view moves to a window, force any pending update immediately.
open override func didMoveToWindow() {
super.didMoveToWindow()
if window != nil {
updateView()
}
}
private func initialSetup() {
if !initialSetupPerformed {
initialSetupPerformed = true
shouldUpdateView = false
setupDidChangeEvent(true)
setup()
setDefaults()
shouldUpdateView = true

View File

@ -36,6 +36,7 @@ open class View: UIView, ViewProtocol, UserInfoable, Clickable {
// MARK: - Combine Properties
//--------------------------------------------------
open var subscribers = Set<AnyCancellable>()
open var subject = PassthroughSubject<Void, Never>()
open var onClickSubscriber: AnyCancellable?
//--------------------------------------------------
@ -58,10 +59,19 @@ open class View: UIView, ViewProtocol, UserInfoable, Clickable {
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
/// When the view moves to a window, force any pending update immediately.
open override func didMoveToWindow() {
super.didMoveToWindow()
if window != nil {
updateView()
}
}
private func initialSetup() {
if !initialSetupPerformed {
initialSetupPerformed = true
shouldUpdateView = false
setupDidChangeEvent(true)
setup()
setDefaults()
shouldUpdateView = true

View File

@ -38,6 +38,7 @@ open class ButtonBase: UIButton, ViewProtocol, UserInfoable, Clickable {
//--------------------------------------------------
/// Set of Subscribers for any Publishers for this Control.
open var subscribers = Set<AnyCancellable>()
open var subject = PassthroughSubject<Void, Never>()
open var onClickSubscriber: AnyCancellable?
@ -97,10 +98,19 @@ open class ButtonBase: UIButton, ViewProtocol, UserInfoable, Clickable {
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
/// When the view moves to a window, force any pending update immediately.
open override func didMoveToWindow() {
super.didMoveToWindow()
if window != nil {
updateView()
}
}
private func initialSetup() {
if !initialSetupPerformed {
initialSetupPerformed = true
shouldUpdateView = false
setupDidChangeEvent(true)
setup()
setDefaults()
shouldUpdateView = true

View File

@ -39,6 +39,7 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
//--------------------------------------------------
/// Set of Subscribers for any Publishers for this Control.
open var subscribers = Set<AnyCancellable>()
open var subject = PassthroughSubject<Void, Never>()
//--------------------------------------------------
// MARK: - Private Properties
@ -192,10 +193,19 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
/// When the view moves to a window, force any pending update immediately.
open override func didMoveToWindow() {
super.didMoveToWindow()
if window != nil {
updateView()
}
}
private func initialSetup() {
if !initialSetupPerformed {
initialSetupPerformed = true
shouldUpdateView = false
setupDidChangeEvent(true)
setup()
setDefaults()
shouldUpdateView = true

View File

@ -37,6 +37,7 @@ open class TextField: UITextField, ViewProtocol, Errorable {
//--------------------------------------------------
/// Set of Subscribers for any Publishers for this Control.
open var subscribers = Set<AnyCancellable>()
open var subject = PassthroughSubject<Void, Never>()
//--------------------------------------------------
// MARK: - Private Properties
@ -98,10 +99,19 @@ open class TextField: UITextField, ViewProtocol, Errorable {
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
/// When the view moves to a window, force any pending update immediately.
open override func didMoveToWindow() {
super.didMoveToWindow()
if window != nil {
updateView()
}
}
private func initialSetup() {
if !initialSetupPerformed {
initialSetupPerformed = true
shouldUpdateView = false
setupDidChangeEvent(true)
setup()
setDefaults()
shouldUpdateView = true

View File

@ -37,6 +37,7 @@ open class TextView: UITextView, ViewProtocol, Errorable {
//--------------------------------------------------
/// Set of Subscribers for any Publishers for this Control.
open var subscribers = Set<AnyCancellable>()
open var subject = PassthroughSubject<Void, Never>()
//--------------------------------------------------
// MARK: - Private Properties
@ -107,10 +108,19 @@ open class TextView: UITextView, ViewProtocol, Errorable {
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
/// When the view moves to a window, force any pending update immediately.
open override func didMoveToWindow() {
super.didMoveToWindow()
if window != nil {
updateView()
}
}
private func initialSetup() {
if !initialSetupPerformed {
initialSetupPerformed = true
shouldUpdateView = false
setupDidChangeEvent(true)
setup()
setDefaults()
shouldUpdateView = true

View File

@ -10,6 +10,8 @@ import UIKit
import Combine
public protocol ViewProtocol: AnyObject, Initable, Resettable, Enabling, Surfaceable, AccessibilityUpdatable {
var subject: PassthroughSubject<Void, Never> { get set }
/// Set of Subscribers for any Publishers for this Control.
var subscribers: Set<AnyCancellable> { get set }
@ -36,28 +38,48 @@ extension ViewProtocol {
/// Called when there are changes in a View based off a change events or from local properties.
public func setNeedsUpdate() {
if shouldUpdateView {
shouldUpdateView = false
//see if this is a view that has children
let parent = self as? any ParentViewProtocol
let children = parent?.getAllChildren()
//if so turn off the shouldUpdate to keep UI
//from blocking
children?.forEach{ $0.shouldUpdateView = false }
updateView()
updateAccessibility()
//if so turn on
children?.forEach{
$0.updateView()
$0.updateAccessibility()
$0.shouldUpdateView = true
// if shouldUpdateView {
// shouldUpdateView = false
//
// //see if this is a view that has children
// let parent = self as? any ParentViewProtocol
// let children = parent?.getAllChildren()
// //if so turn off the shouldUpdate to keep UI
// //from blocking
// children?.forEach{ $0.shouldUpdateView = false }
//
// updateView()
// updateAccessibility()
//
// //if so turn on
// children?.forEach{
// $0.updateView()
// $0.updateAccessibility()
// $0.shouldUpdateView = true
// }
// shouldUpdateView = true
// }
subject.send()
}
shouldUpdateView = true
public func setupDidChangeEvent(_ debounce: Bool = false) {
handlerPublisher(debounce)
.sink { [weak self] _ in
self?.updateView()
}.store(in: &subscribers)
}
public func handlerPublisher(_ debounce: Bool = false) -> AnyPublisher<Void, Never> {
if debounce {
return subject
.debounce(for: .seconds(0.05), scheduler: RunLoop.main)
.eraseToAnyPublisher()
} else {
return subject
.eraseToAnyPublisher()
}
}
}
extension ViewProtocol where Self: UIView {