105 lines
3.2 KiB
Swift
105 lines
3.2 KiB
Swift
//
|
|
// ViewProtocol.swift
|
|
// VDS
|
|
//
|
|
// Created by Matt Bruce on 7/22/22.
|
|
//
|
|
|
|
import Foundation
|
|
import UIKit
|
|
import Combine
|
|
|
|
public protocol ParentViewProtocol: ViewProtocol {
|
|
var children: [any ViewProtocol] { get }
|
|
}
|
|
|
|
extension ParentViewProtocol {
|
|
public func getAllChildren() -> [any ViewProtocol] {
|
|
var allChildren = [any ViewProtocol]()
|
|
|
|
func traverse(view: any ViewProtocol) {
|
|
if let parentView = view as? any ParentViewProtocol {
|
|
for child in parentView.children {
|
|
allChildren.append(child)
|
|
traverse(view: child)
|
|
}
|
|
}
|
|
}
|
|
|
|
traverse(view: self)
|
|
return children
|
|
}
|
|
}
|
|
|
|
public protocol ViewProtocol: AnyObject, Initable, Resettable, Enabling, Surfaceable, AccessibilityUpdatable {
|
|
/// Set of Subscribers for any Publishers for this Control.
|
|
var subscribers: Set<AnyCancellable> { get set }
|
|
|
|
/// Key of whether or not updateView() is called in setNeedsUpdate()
|
|
var shouldUpdateView: Bool { get set }
|
|
|
|
/// Used for setting an implementation for the default Accessible Action
|
|
var accessibilityAction: ((Self) -> Void)? { get set }
|
|
|
|
/// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations.
|
|
func setup()
|
|
|
|
/// Default configurations for values and properties. This is called in the setup() and reset().
|
|
func setDefaults()
|
|
|
|
/// Used to make changes to the View based off a change events or from local properties.
|
|
func updateView()
|
|
|
|
/// Used to update any Accessibility properties.
|
|
func updateAccessibility()
|
|
}
|
|
|
|
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
|
|
}
|
|
shouldUpdateView = true
|
|
}
|
|
}
|
|
}
|
|
|
|
extension ViewProtocol where Self: UIView {
|
|
|
|
/// Helper method for removing a superview and updating Self.
|
|
public func removeFromSuperview(_ view: UIView){
|
|
if view.superview != nil {
|
|
view.removeFromSuperview()
|
|
setNeedsDisplay()
|
|
}
|
|
}
|
|
}
|
|
|
|
extension ViewProtocol where Self: UIControl {
|
|
/// Helper method to assign a completion block to a specific UIControl Event using Combine and stored in the subscribers.
|
|
public func addEvent(event: UIControl.Event, block: @escaping (Self)->()) {
|
|
publisher(for: event)
|
|
.sink(receiveValue: { c in
|
|
block(c)
|
|
}).store(in: &subscribers)
|
|
}
|
|
}
|