105 lines
3.3 KiB
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)
|
|
}
|
|
}
|