Skip to content

Instantly share code, notes, and snippets.

@alexdrone
Created October 16, 2018 14:36
Show Gist options
  • Save alexdrone/3f1ef920f264c5cccdc39363c2aa94ed to your computer and use it in GitHub Desktop.
Save alexdrone/3f1ef920f264c5cccdc39363c2aa94ed to your computer and use it in GitHub Desktop.
Vanilla View Swift
import UIKit
/// Represents the internal state of the view.
public protocol BaseViewState {
init()
}
/// Empty view state.
public final class BaseViewNullState: BaseViewState {
public init() {
// No-op.
}
}
/// The properties passed down to the view.
public protocol BaseViewProps {
init()
}
/// Empty properties.
public final class BaseViewNullProps: BaseViewProps {
public init() {
// No-op.
}
}
public protocol BaseViewDelegate: AnyObject { }
public class BaseView<
StateType: BaseViewState,
PropsType: BaseViewProps>: UIView {
/// The view delegate.
public weak var delegate: BaseViewDelegate?
/// The view current state.
public private(set) var state = StateType() {
didSet {
onStateChange(old: oldValue, new: state)
}
}
/// The view properties.
public var props = PropsType() {
didSet {
onPropsChange(old: oldValue, new: props)
}
}
public override init(frame: CGRect) {
super.init(frame: frame)
initSubviews()
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initSubviews()
}
/// Initialize all of the subviews.
open func initSubviews() {
// Subviews configuration code here.
}
/// The `props` member changed.
/// - note: Subviews to override this method if necessary, the default implementation triggers
/// `setNeedsLayout`.
open func onPropsChange(old: PropsType, new: PropsType) {
// Subviews to override this method if necessary.
setNeedsLayout()
}
/// The `props` member changed.
/// - note: Subviews to override this method if necessary, the default implementation triggers
/// `setNeedsLayout`.
open func onStateChange(old: StateType, new: StateType) {
// Subviews to override this method if necessary.
setNeedsLayout()
}
}
public extension UIResponder {
/// Returns the parent view controller for this `UIResponder`.
public func viewControllerForAncestor() -> UIViewController? {
if self.next is UIViewController {
return self.next as? UIViewController
} else {
if self.next != nil {
return (self.next!).viewControllerForAncestor()
}
else {return nil}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment