vds_ios/VDS/Protocols/ViewProtocol.swift

105 lines
3.3 KiB
Swift

//
// ViewProtocol.swift
// VDS
//
// Created by Matt Bruce on 7/22/22.
//
import Foundation
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 }
/// 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
// }
subject.send()
}
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 {
/// 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)
}
}