diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index ab057e0..5126674 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -8,15 +8,15 @@ jobs: runs-on: macOS-latest strategy: matrix: - destination: ['platform=iOS Simulator,OS=13.1,name=iPhone 8'] - xcode: ['/Applications/Xcode_11.6.app/Contents/Developer'] + destination: ['platform=iOS Simulator,OS=13.1,name=iPhone 11'] + xcode: ['/Applications/Xcode_12.app/Contents/Developer'] steps: - uses: actions/checkout@v1 # Github Actions' machines do in fact have recent versions of Xcode, # but you may have to explicitly switch to them. We explicitly want - # to use Xcode 11, so we use xcode-select to switch to it. - - name: Switch to Xcode 11 - run: sudo xcode-select --switch /Applications/Xcode_11.6.app + # to use Xcode 12, so we use xcode-select to switch to it. + - name: Switch to Xcode 12 + run: sudo xcode-select --switch /Applications/Xcode_12.app # Since we want to be running our tests from Xcode, we need to # generate an .xcodeproj file. Luckly, Swift Package Manager has # build in functionality to do so. diff --git a/Package.swift b/Package.swift index c1a6db8..6fe96a2 100644 --- a/Package.swift +++ b/Package.swift @@ -14,7 +14,8 @@ let package = Package( dependencies: [ // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: "1.0.0"), - .package(url: "https://github.com/0xLeif/Later", from: "0.3.1") + .package(url: "https://github.com/0xLeif/Observation", from: "0.0.2"), + .package(url: "https://github.com/0xLeif/DataObject", from: "0.2.1") ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. @@ -22,7 +23,8 @@ let package = Package( .target( name: "SwiftUIKit", dependencies: [ - "Later" + "Observation", + "DataObject" ]), .testTarget( name: "SwiftUIKitTests", diff --git a/README.md b/README.md index 667a982..4608a30 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,9 @@ UIKit code that is fun to write. +## [Documentation](documentation/Home.md) (WIP) + + ## Example Code ```Swift import UIKit @@ -38,7 +41,7 @@ class ViewController: UIViewController { Spacer(), - Field(value: "SwiftUIKit", + TextField(value: "SwiftUIKit", placeholder: "Some Name", keyboardType: .default) .inputHandler { print("New Name: \($0)") } diff --git a/Sources/SwiftUIKit/Containers/HScroll.swift b/Sources/SwiftUIKit/Containers/HScroll.swift index eb153ea..2b85b59 100644 --- a/Sources/SwiftUIKit/Containers/HScroll.swift +++ b/Sources/SwiftUIKit/Containers/HScroll.swift @@ -10,8 +10,10 @@ import UIKit @available(iOS 9.0, *) public class HScroll: UIView { - public init(withPadding padding: Float = 0, - _ closure: () -> UIView) { + public init( + withPadding padding: Float = 0, + _ closure: () -> UIView + ) { super.init(frame: .zero) let scrollableView = closure() diff --git a/Sources/SwiftUIKit/Containers/HStack.swift b/Sources/SwiftUIKit/Containers/HStack.swift index cfca621..c170dc0 100644 --- a/Sources/SwiftUIKit/Containers/HStack.swift +++ b/Sources/SwiftUIKit/Containers/HStack.swift @@ -24,11 +24,13 @@ public class HStack: UIView { /// - alignment: The layout of arranged views perpendicular to the stack view’s axis (source: UIStackView.Alignment) /// - distribution: The layout that defines the size and position of the arranged views along the stack view’s axis (source: UIStackView.Distribution) /// - closure: A trailing closure that accepts an array of views - public init(withSpacing spacing: Float = 0, - padding: Float = 0, - alignment: UIStackView.Alignment = .fill, - distribution: UIStackView.Distribution = .fill, - _ closure: () -> [UIView]) { + public init( + withSpacing spacing: Float = 0, + padding: Float = 0, + alignment: UIStackView.Alignment = .fill, + distribution: UIStackView.Distribution = .fill, + _ closure: () -> [UIView] + ) { self.spacing = spacing self.padding = padding self.alignment = alignment @@ -45,11 +47,13 @@ public class HStack: UIView { /// - alignment: The layout of arranged views perpendicular to the stack view’s axis (source: UIStackView.Alignment) /// - distribution: The layout that defines the size and position of the arranged views along the stack view’s axis (source: UIStackView.Distribution) /// - closure: A trailing closure that accepts an array of optional views - public init(withSpacing spacing: Float = 0, - padding: Float = 0, - alignment: UIStackView.Alignment = .fill, - distribution: UIStackView.Distribution = .fill, - _ closure: () -> [UIView?]) { + public init( + withSpacing spacing: Float = 0, + padding: Float = 0, + alignment: UIStackView.Alignment = .fill, + distribution: UIStackView.Distribution = .fill, + _ closure: () -> [UIView?] + ) { self.spacing = spacing self.padding = padding self.alignment = alignment @@ -70,7 +74,7 @@ public class HStack: UIView { padding: padding, alignment: alignment, distribution: distribution) - { views } + { views } } public func update(views closure: (inout [UIView]) -> Void) -> Self { diff --git a/Sources/SwiftUIKit/Containers/VScroll.swift b/Sources/SwiftUIKit/Containers/VScroll.swift index 2793fce..f012a09 100644 --- a/Sources/SwiftUIKit/Containers/VScroll.swift +++ b/Sources/SwiftUIKit/Containers/VScroll.swift @@ -10,8 +10,10 @@ import UIKit @available(iOS 9.0, *) public class VScroll: UIView { - public init(withPadding padding: Float = 0, - _ closure: () -> UIView) { + public init( + withPadding padding: Float = 0, + _ closure: () -> UIView + ) { super.init(frame: .zero) let scrollableView = closure() diff --git a/Sources/SwiftUIKit/Containers/VStack.swift b/Sources/SwiftUIKit/Containers/VStack.swift index 6b9c62d..d73755d 100644 --- a/Sources/SwiftUIKit/Containers/VStack.swift +++ b/Sources/SwiftUIKit/Containers/VStack.swift @@ -6,7 +6,6 @@ // import UIKit -import Later /// Vertical StackView @available(iOS 9.0, *) @@ -25,11 +24,13 @@ public class VStack: UIView { /// - alignment: The layout of arranged views perpendicular to the stack view’s axis (source: UIStackView.Alignment) /// - distribution: The layout that defines the size and position of the arranged views along the stack view’s axis (source: UIStackView.Distribution) /// - closure: A trailing closure that accepts an array of views - public init(withSpacing spacing: Float = 0, - padding: Float = 0, - alignment: UIStackView.Alignment = .fill, - distribution: UIStackView.Distribution = .fill, - _ closure: () -> [UIView]) { + public init( + withSpacing spacing: Float = 0, + padding: Float = 0, + alignment: UIStackView.Alignment = .fill, + distribution: UIStackView.Distribution = .fill, + _ closure: () -> [UIView] + ) { self.spacing = spacing self.padding = padding self.alignment = alignment @@ -46,11 +47,13 @@ public class VStack: UIView { /// - alignment: The layout of arranged views perpendicular to the stack view’s axis (source: UIStackView.Alignment) /// - distribution: The layout that defines the size and position of the arranged views along the stack view’s axis (source: UIStackView.Distribution) /// - closure: A trailing closure that accepts an array of optional views - public init(withSpacing spacing: Float = 0, - padding: Float = 0, - alignment: UIStackView.Alignment = .fill, - distribution: UIStackView.Distribution = .fill, - _ closure: () -> [UIView?]) { + public init( + withSpacing spacing: Float = 0, + padding: Float = 0, + alignment: UIStackView.Alignment = .fill, + distribution: UIStackView.Distribution = .fill, + _ closure: () -> [UIView?] + ) { self.spacing = spacing self.padding = padding self.alignment = alignment @@ -71,7 +74,7 @@ public class VStack: UIView { padding: padding, alignment: alignment, distribution: distribution) - { views } + { views } } @discardableResult diff --git a/Sources/SwiftUIKit/Extensions/NSLayoutConstraint+SwiftUIKit.swift b/Sources/SwiftUIKit/Extensions/NSLayoutConstraint+SwiftUIKit.swift index d1934b1..1b97269 100644 --- a/Sources/SwiftUIKit/Extensions/NSLayoutConstraint+SwiftUIKit.swift +++ b/Sources/SwiftUIKit/Extensions/NSLayoutConstraint+SwiftUIKit.swift @@ -46,4 +46,18 @@ public extension UIView { constraint.isConnected(toAnchor: bottomAnchor) } } + + /// The height constraints held by the view + var heightConstraints: [NSLayoutConstraint] { + constraints.filter { (constraint) -> Bool in + constraint.isConnected(toAnchor: heightAnchor) + } + } + + /// The width constraints held by the view + var widthConstraints: [NSLayoutConstraint] { + constraints.filter { (constraint) -> Bool in + constraint.isConnected(toAnchor: widthAnchor) + } + } } diff --git a/Sources/SwiftUIKit/Extensions/NSObjectProtocol+SwiftUIKit.swift b/Sources/SwiftUIKit/Extensions/NSObjectProtocol+SwiftUIKit.swift deleted file mode 100644 index 68fca11..0000000 --- a/Sources/SwiftUIKit/Extensions/NSObjectProtocol+SwiftUIKit.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// NSObjectProtocol+SwiftUIKit.swift -// -// -// Created by Zach Eriksen on 10/30/19. -// - -import Foundation - -public extension NSObjectProtocol { - - /// Modify the object - /// - Parameters: - /// - closure: A trailing closure that receives itself inside the closue - @discardableResult - func configure(_ closure: (Self) -> Void) -> Self { - closure(self) - - return self - } -} diff --git a/Sources/SwiftUIKit/Extensions/SwiftFu+.swift b/Sources/SwiftUIKit/Extensions/SwiftFu+.swift new file mode 100644 index 0000000..8507f92 --- /dev/null +++ b/Sources/SwiftUIKit/Extensions/SwiftFu+.swift @@ -0,0 +1,8 @@ +// +// SwiftFu+.swift +// +// +// Created by Leif on 3/16/21. +// + +import SwiftFu diff --git a/Sources/SwiftUIKit/Extensions/UIAppearance+SwiftUIKit.swift b/Sources/SwiftUIKit/Extensions/UIAppearance+SwiftUIKit.swift index 07b25ef..1ad5b9c 100644 --- a/Sources/SwiftUIKit/Extensions/UIAppearance+SwiftUIKit.swift +++ b/Sources/SwiftUIKit/Extensions/UIAppearance+SwiftUIKit.swift @@ -6,13 +6,15 @@ // import UIKit -import Later @available(iOS 9.0, *) public extension UIAppearance where Self: UIView { - func contract(_ closure: (Self) -> Contract) -> ContractView { - ContractView(view: self) { view in - closure(view) - } + func observed( + initialValue: Value, + onChangeHandler: @escaping (_ newValue: Value?, _ view: Self) -> Void + ) -> ObservedView { + ObservedView(view: self, + initialValue: initialValue, + onChangeHandler: onChangeHandler) } } diff --git a/Sources/SwiftUIKit/Extensions/UIView+Chain.swift b/Sources/SwiftUIKit/Extensions/UIView+Chain.swift new file mode 100644 index 0000000..c8f91ed --- /dev/null +++ b/Sources/SwiftUIKit/Extensions/UIView+Chain.swift @@ -0,0 +1,114 @@ +// +// UIView+Chain.swift +// SwiftUIKit +// +// Created by Zach Eriksen on 8/26/20. +// + +import E +import UIKit +import Chain + +@available(iOS 9.0, *) +private extension UIView { + static func chain( + link: Chain, + update: @escaping (UIView) -> Void, + shouldBackground: Bool = false, + centeredLoadingView: UIView? = nil, + embeddedLoadingView: UIView? = nil + ) -> UIView { + let view = UIView() + + if let embeddedLoadingView = embeddedLoadingView { + view.embed { + embeddedLoadingView + } + } else { + view.center { + centeredLoadingView ?? LoadingView().start() + } + } + + let chainEnd: Chain = .complete( + .void { + update(view) + } + ) + + var output = Variable.void + + if shouldBackground { + output = Chain.background( + .out { + link.run() + }, + chainEnd + ) + .run() + } else { + output = Chain.link( + .out { + link.run() + }, + chainEnd + ) + .run() + } + + print("\(#function): \(output)") + + return view + } +} + +@available(iOS 9.0, *) +public extension UIView { + static func chain( + link: Chain, + update: @escaping (UIView) -> Void, + centeredLoadingView: UIView? = nil + ) -> UIView { + chain(link: link, + update: update, + shouldBackground: false, + centeredLoadingView: centeredLoadingView, + embeddedLoadingView: nil) + } + + static func chain( + link: Chain, + update: @escaping (UIView) -> Void, + embeddedLoadingView: UIView + ) -> UIView { + chain(link: link, + update: update, + shouldBackground: false, + centeredLoadingView: nil, + embeddedLoadingView: embeddedLoadingView) + } + + static func background( + link: Chain, + update: @escaping (UIView) -> Void, + centeredLoadingView: UIView? = nil + ) -> UIView { + chain(link: link, + update: update, + shouldBackground: true, + centeredLoadingView: centeredLoadingView, + embeddedLoadingView: nil) + } + + static func background( + link: Chain, + update: @escaping (UIView) -> Void, + embeddedLoadingView: UIView + ) -> UIView { + chain(link: link, + update: update, + shouldBackground: true, + centeredLoadingView: nil, + embeddedLoadingView: embeddedLoadingView) + } +} diff --git a/Sources/SwiftUIKit/Extensions/UIView+Later.swift b/Sources/SwiftUIKit/Extensions/UIView+Later.swift deleted file mode 100644 index 9b43ae6..0000000 --- a/Sources/SwiftUIKit/Extensions/UIView+Later.swift +++ /dev/null @@ -1,87 +0,0 @@ -// -// UIView+Later.swift -// SwiftUIKit -// -// Created by Zach Eriksen on 8/26/20. -// - -import UIKit -import Later - -@available(iOS 9.0, *) -public extension UIView { - static func later(_ laterView: (Later.Type) -> LaterValue) -> UIView { - let view = UIView() - - view.center { - LoadingView() - .start() - } - - laterView(Later.self) - .whenSuccess { embeddedView in - Later.main { - view.clear() - .embed { - embeddedView - } - } - - } - - return view - } - - static func later(centeredLoadingView: UIView, - withSize size: CGSize? = nil, - _ laterView: (Later.Type) -> LaterValue) -> UIView { - - let view = UIView() - - view.center { - centeredLoadingView - .configure { - if let size = size { - $0.frame(height: Float(size.height), - width: Float(size.width)) - } - } - } - - laterView(Later.self) - .whenSuccess { embeddedView in - Later.main { - view.clear() - .embed { - embeddedView - } - } - - } - - return view - } - - static func later(embeddedLoadingView: UIView, - withPadding padding: Float = 0, - _ laterView: (Later.Type) -> LaterValue) -> UIView { - let view = UIView() - - view.embed(withPadding: padding) { - embeddedLoadingView - } - - laterView(Later.self) - .whenSuccess { embeddedView in - Later.main { - view.clear() - .embed { - embeddedView - } - } - - } - - return view - } -} diff --git a/Sources/SwiftUIKit/Extensions/UIView+SwiftUIKit.swift b/Sources/SwiftUIKit/Extensions/UIView+SwiftUIKit.swift index dc92564..24e1c82 100644 --- a/Sources/SwiftUIKit/Extensions/UIView+SwiftUIKit.swift +++ b/Sources/SwiftUIKit/Extensions/UIView+SwiftUIKit.swift @@ -17,9 +17,11 @@ public enum Padding { @available(iOS 9.0, *) public extension UIView { - convenience init(withPadding padding: Float = 0, - backgroundColor: UIColor? = .clear, - _ closure: (() -> UIView)? = nil) { + convenience init( + withPadding padding: Float = 0, + backgroundColor: UIColor? = .clear, + _ closure: (() -> UIView)? = nil + ) { self.init(frame: .zero) self.backgroundColor = backgroundColor @@ -27,9 +29,11 @@ public extension UIView { _ = closure.map { embed(withPadding: padding, $0) } } - convenience init(withPadding padding: [Padding], - backgroundColor: UIColor? = .clear, - _ closure: (() -> UIView)? = nil) { + convenience init( + withPadding padding: [Padding], + backgroundColor: UIColor? = .clear, + _ closure: (() -> UIView)? = nil + ) { self.init(frame: .zero) self.backgroundColor = backgroundColor @@ -46,12 +50,14 @@ public extension UIView { /// - axis: Keys that specify a horizontal or vertical layout constraint between objects (source: NSLayoutConstraint.Axis) /// - closure: A trailing closure that accepts an array of views @discardableResult - func stack(withSpacing spacing: Float = 0, - padding: Float = 0, - alignment: UIStackView.Alignment = .fill, - distribution: UIStackView.Distribution = .fill, - axis: NSLayoutConstraint.Axis, - _ closure: () -> [UIView?]) -> Self { + func stack( + withSpacing spacing: Float = 0, + padding: Float = 0, + alignment: UIStackView.Alignment = .fill, + distribution: UIStackView.Distribution = .fill, + axis: NSLayoutConstraint.Axis, + _ closure: () -> [UIView?] + ) -> Self { let viewsInVStack = closure() .compactMap { $0 } @@ -77,12 +83,14 @@ public extension UIView { /// - axis: Keys that specify a horizontal or vertical layout constraint between objects (source: NSLayoutConstraint.Axis) /// - closure: A trailing closure that accepts an array of views @discardableResult - func stack(withSpacing spacing: Float = 0, - padding: [Padding], - alignment: UIStackView.Alignment = .fill, - distribution: UIStackView.Distribution = .fill, - axis: NSLayoutConstraint.Axis, - _ closure: () -> [UIView?]) -> Self { + func stack( + withSpacing spacing: Float = 0, + padding: [Padding], + alignment: UIStackView.Alignment = .fill, + distribution: UIStackView.Distribution = .fill, + axis: NSLayoutConstraint.Axis, + _ closure: () -> [UIView?] + ) -> Self { let viewsInVStack = closure() .compactMap { $0 } @@ -107,11 +115,13 @@ public extension UIView { /// - distribution: The layout that defines the size and position of the arranged views along the stack view’s axis (source: UIStackView.Distribution) /// - closure: A trailing closure that accepts an array of views @discardableResult - func vstack(withSpacing spacing: Float = 0, - padding: Float = 0, - alignment: UIStackView.Alignment = .fill, - distribution: UIStackView.Distribution = .fill, - _ closure: () -> [UIView?]) -> Self { + func vstack( + withSpacing spacing: Float = 0, + padding: Float = 0, + alignment: UIStackView.Alignment = .fill, + distribution: UIStackView.Distribution = .fill, + _ closure: () -> [UIView?] + ) -> Self { return stack(withSpacing: spacing, padding: padding, alignment: alignment, @@ -128,11 +138,13 @@ public extension UIView { /// - distribution: The layout that defines the size and position of the arranged views along the stack view’s axis (source: UIStackView.Distribution) /// - closure: A trailing closure that accepts an array of views @discardableResult - func vstack(withSpacing spacing: Float = 0, - padding: [Padding], - alignment: UIStackView.Alignment = .fill, - distribution: UIStackView.Distribution = .fill, - _ closure: () -> [UIView?]) -> Self { + func vstack( + withSpacing spacing: Float = 0, + padding: [Padding], + alignment: UIStackView.Alignment = .fill, + distribution: UIStackView.Distribution = .fill, + _ closure: () -> [UIView?] + ) -> Self { return stack(withSpacing: spacing, padding: padding, alignment: alignment, @@ -149,11 +161,13 @@ public extension UIView { /// - distribution: The layout that defines the size and position of the arranged views along the stack view’s axis (source: UIStackView.Distribution) /// - closure: A trailing closure that accepts an array of views @discardableResult - func hstack(withSpacing spacing: Float = 0, - padding: Float = 0, - alignment: UIStackView.Alignment = .fill, - distribution: UIStackView.Distribution = .fill, - _ closure: () -> [UIView?]) -> Self { + func hstack( + withSpacing spacing: Float = 0, + padding: Float = 0, + alignment: UIStackView.Alignment = .fill, + distribution: UIStackView.Distribution = .fill, + _ closure: () -> [UIView?] + ) -> Self { return stack(withSpacing: spacing, padding: padding, alignment: alignment, @@ -170,11 +184,13 @@ public extension UIView { /// - distribution: The layout that defines the size and position of the arranged views along the stack view’s axis (source: UIStackView.Distribution) /// - closure: A trailing closure that accepts an array of views @discardableResult - func hstack(withSpacing spacing: Float = 0, - padding: [Padding], - alignment: UIStackView.Alignment = .fill, - distribution: UIStackView.Distribution = .fill, - _ closure: () -> [UIView?]) -> Self { + func hstack( + withSpacing spacing: Float = 0, + padding: [Padding], + alignment: UIStackView.Alignment = .fill, + distribution: UIStackView.Distribution = .fill, + _ closure: () -> [UIView?] + ) -> Self { return stack(withSpacing: spacing, padding: padding, alignment: alignment, @@ -188,8 +204,10 @@ public extension UIView { /// - withPadding: The amount of space between the embedded view and this view /// - closure: A trailing closure that accepts a view @discardableResult - func embed(withPadding padding: Float = 0, - _ closure: () -> UIView) -> Self { + func embed( + withPadding padding: Float = 0, + _ closure: () -> UIView + ) -> Self { let viewToEmbed = closure() viewToEmbed.translatesAutoresizingMaskIntoConstraints = false addSubview(viewToEmbed) @@ -226,8 +244,10 @@ public extension UIView { /// - withPadding: The amount of space between the embedded view and this view /// - closure: A trailing closure that accepts a view @discardableResult - func embed(withPadding padding: [Padding], - _ closure: () -> UIView) -> Self { + func embed( + withPadding padding: [Padding], + _ closure: () -> UIView + ) -> Self { let viewToEmbed = closure() viewToEmbed.translatesAutoresizingMaskIntoConstraints = false addSubview(viewToEmbed) @@ -321,26 +341,39 @@ public extension UIView { /// - width: Value for the widthAnchor @available(iOS 10.0, *) @discardableResult - func update(height: Float? = nil, width: Float? = nil) -> Self { - if let height = height { - constraints.first { (constraint) -> Bool in - constraint.firstAnchor == heightAnchor + func update( + height: Float? = nil, + width: Float? = nil, + animated: Bool = false + ) -> Self { + guard animated else { + if let height = height { + constraints.first { (constraint) -> Bool in + constraint.firstAnchor == heightAnchor }?.constant = CGFloat(height) + } + + if let width = width { + constraints.first { (constraint) -> Bool in + constraint.firstAnchor == widthAnchor + }?.constant = CGFloat(width) + } + return self } - if let width = width { - constraints.first { (constraint) -> Bool in - constraint.firstAnchor == widthAnchor - }?.constant = CGFloat(width) + Self.animate(withDuration: 1) { + self.update(height: height, width: width) + self.layoutIfNeeded() } + return self } /// Update a padding anchor's constant value @available(iOS 10.0, *) @discardableResult - func update(padding: Padding) -> Self { + func update(padding: Padding, animated: Bool = false) -> Self { switch padding { case .top(let value): topConstraints.first?.constant = CGFloat(value) @@ -352,14 +385,20 @@ public extension UIView { trailingConstraints.first?.constant = CGFloat(-value) } + if animated { + Self.animate(withDuration: 1) { + self.layoutIfNeeded() + } + } + return self } /// Update an array of padding anchors' constant values @available(iOS 10.0, *) @discardableResult - func update(padding: [Padding]) -> Self { - padding.forEach { update(padding: $0) } + func update(padding: [Padding], animated: Bool = false) -> Self { + padding.forEach { update(padding: $0, animated: animated) } return self } @@ -367,13 +406,13 @@ public extension UIView { /// Update all padding anchors' constant value @available(iOS 10.0, *) @discardableResult - func update(padding: Float) -> Self { + func update(padding: Float, animated: Bool = false) -> Self { update(padding: [ .top(padding), .bottom(padding), .leading(padding), .trailing(padding) - ]) + ], animated: animated) return self } @@ -445,7 +484,11 @@ public extension UIView { /// Constrains the View's centerAnchors @discardableResult - func center(xOffset: Float? = nil, yOffset: Float? = nil, in view: UIView) -> Self { + func center( + xOffset: Float? = nil, + yOffset: Float? = nil, + in view: UIView + ) -> Self { translatesAutoresizingMaskIntoConstraints = false view.addSubview(self) @@ -460,34 +503,38 @@ public extension UIView { } @discardableResult - func animate(withDuration duration: TimeInterval, - animation: @escaping (UIView) -> Void, - completion: ((UIView) -> Void)? = nil) -> Self { + func animate( + withDuration duration: TimeInterval, + animation: @escaping (UIView) -> Void, + completion: ((UIView) -> Void)? = nil + ) -> Self { UIView.animate(withDuration: duration, animations: { animation(self) }) { (isComplete) in - if isComplete { - completion?(self) - } + if isComplete { + completion?(self) + } } return self } @discardableResult - func animate(withDuration duration: TimeInterval, - delay: TimeInterval, - options: UIView.AnimationOptions, - animation: @escaping (UIView) -> Void, - completion: ((UIView) -> Void)? = nil) -> Self { + func animate( + withDuration duration: TimeInterval, + delay: TimeInterval, + options: UIView.AnimationOptions, + animation: @escaping (UIView) -> Void, + completion: ((UIView) -> Void)? = nil + ) -> Self { UIView.animate(withDuration: duration, delay: delay, options: options, animations: { animation(self) }) { (isComplete) in - if isComplete { - completion?(self) - } + if isComplete { + completion?(self) + } } return self @@ -521,7 +568,7 @@ public extension UIView { animate(withDuration: duration, animation: { view in view.alpha = 0 - }) { view in + }) { view in view.isHidden = true view.alpha = 1 @@ -539,7 +586,7 @@ public extension UIView { animate(withDuration: duration, animation: { view in view.alpha = 1 - }) { view in + }) { view in view.isHidden = false view.alpha = 1 @@ -556,9 +603,11 @@ public extension UIView { } @discardableResult - func accessibility(label: String? = nil, - identifier: String? = nil, - traits: UIAccessibilityTraits? = nil) -> Self { + func accessibility( + label: String? = nil, + identifier: String? = nil, + traits: UIAccessibilityTraits? = nil + ) -> Self { label.map { accessibilityLabel = $0 } identifier.map { accessibilityIdentifier = $0 } diff --git a/Sources/SwiftUIKit/Extensions/UIViewController+SwiftUIKit.swift b/Sources/SwiftUIKit/Extensions/UIViewController+SwiftUIKit.swift index c79c281..5c6f56d 100644 --- a/Sources/SwiftUIKit/Extensions/UIViewController+SwiftUIKit.swift +++ b/Sources/SwiftUIKit/Extensions/UIViewController+SwiftUIKit.swift @@ -37,9 +37,11 @@ public extension UIViewController { } /// Go without the Navigation Controller using the current ViewController to present the new ViewController - func go(to viewController: UIViewController, - style: Navigate.NavigationStyle, - completion: (() -> Void)? = nil) { + func go( + to viewController: UIViewController, + style: Navigate.NavigationStyle, + completion: (() -> Void)? = nil + ) { Navigate.shared.go(from: self, to: viewController, style: style, @@ -47,9 +49,11 @@ public extension UIViewController { } /// Navigate with the Navigation Controller to the new ViewController - func navigate(_ viewController: UIViewController, - style: Navigate.NavigationStyle, - completion: (() -> Void)? = nil) { + func navigate( + _ viewController: UIViewController, + style: Navigate.NavigationStyle, + completion: (() -> Void)? = nil + ) { Navigate.shared.go(viewController, style: style, completion: completion) diff --git a/Sources/SwiftUIKit/Navigation/Navigate.swift b/Sources/SwiftUIKit/Navigation/Navigate.swift index f1db03b..4b4046e 100644 --- a/Sources/SwiftUIKit/Navigation/Navigate.swift +++ b/Sources/SwiftUIKit/Navigation/Navigate.swift @@ -45,6 +45,9 @@ public class Navigate { private var didTapToastHandler: ((UIView) -> Void)? public static var shared: Navigate = Navigate() + public init(controller: UINavigationController? = nil) { + configure(controller: controller) + } // MARK: Configure NavigationController @@ -116,9 +119,11 @@ public class Navigate { /// - Parameters: /// - viewController: UIViewController to navigate to /// - style: Style of navigation - public func go(_ viewController: UIViewController, - style: NavigationStyle, - completion: (() -> Void)? = nil) { + public func go( + _ viewController: UIViewController, + style: NavigationStyle, + completion: (() -> Void)? = nil + ) { guard let controller = navigationController else { print("Navigate \(#function) Error!") @@ -140,10 +145,12 @@ public class Navigate { /// - from: The UIViewController that is handling the navigation /// - viewController: UIViewController to navigate to /// - style: Style of navigation - public func go(from: UIViewController, - to: UIViewController, - style: NavigationStyle, - completion: (() -> Void)? = nil) { + public func go( + from: UIViewController, + to: UIViewController, + style: NavigationStyle, + completion: (() -> Void)? = nil + ) { switch style { @@ -197,11 +204,13 @@ public class Navigate { /// - withactions: Array of action objects to be added to the Alert /// - secondsToPersist: Amount of seconds the Alert should show before dismissing itself /// - closure: A closure that is passed the UIAlertController before presenting it - public func alert(title: String, - message: String, - withActions actions: [UIAlertAction] = [], - secondsToPersist: Double?, - _ closure: ((UIAlertController) -> Void)? = nil) { + public func alert( + title: String, + message: String, + withActions actions: [UIAlertAction] = [], + secondsToPersist: Double?, + _ closure: ((UIAlertController) -> Void)? = nil + ) { let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) @@ -228,10 +237,12 @@ public class Navigate { /// - message: Message of the UIAlertController /// - withactions: Array of action objects to be added to the ActionSheet /// - closure: A closure that is passed the UIAlertController before presenting it - public func actionSheet(title: String, - message: String, - withActions actions: [UIAlertAction] = [], - _ closure: ((UIAlertController) -> Void)? = nil) { + public func actionSheet( + title: String, + message: String, + withActions actions: [UIAlertAction] = [], + _ closure: ((UIAlertController) -> Void)? = nil + ) { let actionSheet = UIAlertController(title: title, message: message, preferredStyle: .actionSheet) @@ -255,14 +266,16 @@ public class Navigate { /// - tapHandler: What happens when the user taps on the Toast (default: { $0.removeFromSuperview() }) /// - closure: A trailing closure that accepts a view @available(iOS 11.0, *) - public func toast(style: ToastStyle = .custom, - pinToTop: Bool = true, - secondsToPersist: Double? = nil, - animationInDuration: Double = 0.5, - animationOutDuration: Double = 0.5, - padding: Float = 8, - tapHandler: @escaping (UIView) -> Void = { $0.removeFromSuperview() }, - _ closure: @escaping () -> UIView) { + public func toast( + style: ToastStyle = .custom, + pinToTop: Bool = true, + secondsToPersist: Double? = nil, + animationInDuration: Double = 0.5, + animationOutDuration: Double = 0.5, + padding: Float = 8, + tapHandler: @escaping (UIView) -> Void = { $0.removeFromSuperview() }, + _ closure: @escaping () -> UIView + ) { // Don't allow more than one Toast to be present guard toast == nil else { @@ -281,12 +294,12 @@ public class Navigate { .configure { $0.backgroundColor = style.color $0.clipsToBounds = true - } - .layer(cornerRadius: 8) + } + .layer(cornerRadius: 8) } .padding(padding) - + .gesture { UITapGestureRecognizer(target: self, action: #selector(userTappedOnToast)) } } @@ -294,13 +307,13 @@ public class Navigate { toast?.alpha = 0 guard let controller = navigationController, - let containerView = controller.visibleViewController?.view, - let toast = toast else { - destroyToast() - print("Navigate \(#function) Error!") - print("Issue trying to dismiss presentingViewController") - print("Error: Could not unwrap navigationController") - return + let containerView = controller.visibleViewController?.view, + let toast = toast else { + destroyToast() + print("Navigate \(#function) Error!") + print("Issue trying to dismiss presentingViewController") + print("Error: Could not unwrap navigationController") + return } controller.visibleViewController?.view.addSubview(toast) diff --git a/Sources/SwiftUIKit/Views/Button.swift b/Sources/SwiftUIKit/Views/Button.swift index d6ae60f..2f39660 100644 --- a/Sources/SwiftUIKit/Views/Button.swift +++ b/Sources/SwiftUIKit/Views/Button.swift @@ -11,11 +11,13 @@ import UIKit public class Button: UIButton { private var action: (() -> Void)? - public init(_ title: String, - titleColor: UIColor? = nil, - backgroundColor: UIColor? = nil, - forEvent event: UIControl.Event = .touchUpInside, - _ action: (() -> Void)? = nil) { + public init( + title: String, + titleColor: UIColor? = nil, + backgroundColor: UIColor? = nil, + forEvent event: UIControl.Event = .touchUpInside, + action: (() -> Void)? = nil + ) { self.action = action super.init(frame: .zero) @@ -27,15 +29,17 @@ public class Button: UIButton { accessibility(label: title, traits: .button) } - public init(action: (() -> Void)? = nil, - forEvent event: UIControl.Event = .touchUpInside, - _ closure: () -> UIView) { + public init( + forEvent event: UIControl.Event = .touchUpInside, + action: (() -> Void)? = nil, + labelView: () -> UIView + ) { self.action = action super.init(frame: .zero) embed { - closure() - .gesture { UITapGestureRecognizer(target: self, action: #selector(handleButtonTap)) } + labelView() + .gesture { UITapGestureRecognizer(target: self, action: #selector(handleButtonTap)) } } self.addTarget(self, action: #selector(handleButtonTap), for: event) diff --git a/Sources/SwiftUIKit/Views/CollectionView.swift b/Sources/SwiftUIKit/Views/CollectionView.swift index 2f5014f..8c2be4d 100644 --- a/Sources/SwiftUIKit/Views/CollectionView.swift +++ b/Sources/SwiftUIKit/Views/CollectionView.swift @@ -39,7 +39,7 @@ public class CollectionView: UICollectionView { fileprivate var targetContentOffsetForHandler: ((_ proposed: CGPoint) -> CGPoint)? = nil fileprivate var layoutSizeForItemHandler: ((UICollectionViewLayout, IndexPath) -> CGSize)? = nil fileprivate var transitionLayoutForHandler: ((_ old: UICollectionViewLayout, _ new: UICollectionViewLayout) -> UICollectionViewTransitionLayout)? = nil - + fileprivate var didBeginMultipleSelectionInteractionAtHandler: ((IndexPath) -> ())? = nil fileprivate var didEndMultipleSelectionInteractionHandler: ((UICollectionView) -> ())? = nil fileprivate var shouldBeginMultipleSelectionInteractionAtHandler: ((IndexPath) -> Bool)? = nil @@ -95,8 +95,10 @@ public extension CollectionView { } @discardableResult - func update(shouldReloadData: Bool = false, - _ closure: ([[CellDisplayable]]) -> [[CellDisplayable]]) -> Self { + func update( + shouldReloadData: Bool = false, + _ closure: ([[CellDisplayable]]) -> [[CellDisplayable]] + ) -> Self { data = closure(data) if shouldReloadData { @@ -107,8 +109,10 @@ public extension CollectionView { } @discardableResult - func append(shouldReloadData: Bool = false, - _ closure: () -> [[CellDisplayable]]) -> Self { + func append( + shouldReloadData: Bool = false, + _ closure: () -> [[CellDisplayable]] + ) -> Self { data += closure() if shouldReloadData { @@ -198,7 +202,11 @@ public extension CollectionView { } @discardableResult - func scrollToItem(at indexPath: IndexPath, at position: UICollectionView.ScrollPosition, animated: Bool = true) -> Self { + func scrollToItem( + at indexPath: IndexPath, + at position: UICollectionView.ScrollPosition, + animated: Bool = true + ) -> Self { super.scrollToItem(at: indexPath, at: position, animated: animated) return self @@ -213,7 +221,11 @@ public extension CollectionView { } @discardableResult - func selectItem(at indexPath: IndexPath, animated: Bool, scrollPosition: UICollectionView.ScrollPosition) -> Self { + func selectItem( + at indexPath: IndexPath, + animated: Bool, + scrollPosition: UICollectionView.ScrollPosition + ) -> Self { super.selectItem(at: indexPath, animated: animated, scrollPosition: scrollPosition) return self @@ -258,7 +270,7 @@ public extension CollectionView { public extension CollectionView { @discardableResult func set(backgroundView - : UIView) -> Self { + : UIView) -> Self { self.backgroundView = backgroundView return self @@ -332,7 +344,11 @@ extension CollectionView: UICollectionViewDataSource { return titles } - public func collectionView(_ collectionView: UICollectionView, indexPathForIndexTitle title: String, at index: Int) -> IndexPath { + public func collectionView( + _ collectionView: UICollectionView, + indexPathForIndexTitle title: String, + at index: Int + ) -> IndexPath { IndexPath(index: index) } } @@ -496,7 +512,11 @@ extension CollectionView: UICollectionViewDelegate { didUnhighlightItemAtHandler?(indexPath) } - public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { + public func collectionView( + _ collectionView: UICollectionView, + willDisplay cell: UICollectionViewCell, + forItemAt indexPath: IndexPath + ) { willDisplayCellHandler?(cell as! CollectionViewCell, indexPath) } @@ -504,7 +524,11 @@ extension CollectionView: UICollectionViewDelegate { didEndDisplayingCell?(cell as! CollectionViewCell, indexPath) } - public func collectionView(_ collectionView: UICollectionView, transitionLayoutForOldLayout fromLayout: UICollectionViewLayout, newLayout toLayout: UICollectionViewLayout) -> UICollectionViewTransitionLayout { + public func collectionView( + _ collectionView: UICollectionView, + transitionLayoutForOldLayout fromLayout: UICollectionViewLayout, + newLayout toLayout: UICollectionViewLayout + ) -> UICollectionViewTransitionLayout { transitionLayoutForHandler?(fromLayout, toLayout) ?? UICollectionViewTransitionLayout(currentLayout: fromLayout, nextLayout: toLayout) } @@ -597,8 +621,8 @@ extension CollectionView: UICollectionViewDelegateFlowLayout { /// - section: section which will be used to get value from array /// - Returns: First value of array if array's count isn't equal `numberOfSections`, value from given index if array's count is equal to `numberOfSections` and nil if array is nil. func returnValidValue(for array: [T]?, section: Int) -> T? { - if let array = array, - array.count != 0 { + if let array = array, + array.count != 0 { if array.count != numberOfSections || section > numberOfSections { @@ -613,11 +637,19 @@ extension CollectionView: UICollectionViewDelegateFlowLayout { return nil } - public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + public func collectionView( + _ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + sizeForItemAt indexPath: IndexPath + ) -> CGSize { layoutSizeForItemHandler?(collectionViewLayout, indexPath) ?? CGSize(width: 60, height: 60) } - public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { + public func collectionView( + _ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + insetForSectionAt section: Int + ) -> UIEdgeInsets { if let inset = returnValidValue(for: sectionsInsets, section: section) { return inset } @@ -626,7 +658,11 @@ extension CollectionView: UICollectionViewDelegateFlowLayout { } - public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { + public func collectionView( + _ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + minimumLineSpacingForSectionAt section: Int + ) -> CGFloat { if let spacing = returnValidValue(for: minimumLineSpacingForSections, section: section) { return spacing } @@ -634,7 +670,11 @@ extension CollectionView: UICollectionViewDelegateFlowLayout { return 10 } - public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { + public func collectionView( + _ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + minimumInteritemSpacingForSectionAt section: Int + ) -> CGFloat { if let spacing = returnValidValue(for: minimumInteritemSpacingForSections, section: section) { return spacing } @@ -642,7 +682,11 @@ extension CollectionView: UICollectionViewDelegateFlowLayout { return 5 } - public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { + public func collectionView( + _ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + referenceSizeForHeaderInSection section: Int + ) -> CGSize { if let size = returnValidValue(for: headerSizesForSections, section: section) { return size } @@ -650,7 +694,11 @@ extension CollectionView: UICollectionViewDelegateFlowLayout { return .zero } - public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { + public func collectionView( + _ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + referenceSizeForFooterInSection section: Int + ) -> CGSize { if let size = returnValidValue(for: footerSizeForSections, section: section) { return size } diff --git a/Sources/SwiftUIKit/Views/ContainerView.swift b/Sources/SwiftUIKit/Views/ContainerView.swift index 4fc0420..f6c87c4 100644 --- a/Sources/SwiftUIKit/Views/ContainerView.swift +++ b/Sources/SwiftUIKit/Views/ContainerView.swift @@ -12,7 +12,10 @@ public class ContainerView: UIView { private weak var parentViewController: UIViewController? var viewController: UIViewController? - public init(parent: UIViewController, child: () -> UIViewController) { + public init( + parent: UIViewController, + child: () -> UIViewController + ) { parentViewController = parent viewController = child() super.init(frame: .zero) @@ -29,8 +32,8 @@ public class ContainerView: UIView { private extension ContainerView { func embedViewController() { guard let parent = parentViewController, - let child = viewController else { - return + let child = viewController else { + return } parent.addChild(child) diff --git a/Sources/SwiftUIKit/Views/ContractView.swift b/Sources/SwiftUIKit/Views/ContractView.swift deleted file mode 100644 index 96d71be..0000000 --- a/Sources/SwiftUIKit/Views/ContractView.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// ContractView.swift -// -// -// Created by Zach Eriksen on 8/25/20. -// - -import UIKit -import Later - -@available(iOS 9.0, *) -public class ContractView: UIView where View: UIView { - public var contract: Contract? - - public init(_ closure: (UIView) -> Contract) { - super.init(frame: .zero) - - let view = UIView() - - self.contract = closure(view) - - embed { - view - } - - contract?.value = contract?.value - } - - public init(view: View, _ closure: (View) -> Contract) { - super.init(frame: .zero) - - self.contract = closure(view) - - embed { - view - } - - contract?.value = contract?.value - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} diff --git a/Sources/SwiftUIKit/Views/Divider.swift b/Sources/SwiftUIKit/Views/Divider.swift index c17b140..3ca5663 100644 --- a/Sources/SwiftUIKit/Views/Divider.swift +++ b/Sources/SwiftUIKit/Views/Divider.swift @@ -9,8 +9,10 @@ import UIKit @available(iOS 9.0, *) public class Divider: UIView { - public init(_ axis: NSLayoutConstraint.Axis = .horizontal, - color: UIColor? = .systemGray) { + public init( + _ axis: NSLayoutConstraint.Axis = .horizontal, + color: UIColor? = .systemGray + ) { super.init(frame: .zero) self.backgroundColor = color diff --git a/Sources/SwiftUIKit/Views/EffectView.swift b/Sources/SwiftUIKit/Views/EffectView.swift index 57bf931..3053316 100644 --- a/Sources/SwiftUIKit/Views/EffectView.swift +++ b/Sources/SwiftUIKit/Views/EffectView.swift @@ -9,7 +9,10 @@ import UIKit @available(iOS 9.0, *) public class EffectView: UIVisualEffectView { - public init(for effect: UIVisualEffect? = nil, closure: () -> UIView) { + public init( + for effect: UIVisualEffect? = nil, + closure: () -> UIView + ) { super.init(effect: effect) contentView.embed { @@ -24,7 +27,10 @@ public class EffectView: UIVisualEffectView { @available(iOS 10.0, *) public class BlurView: UIVisualEffectView { - public init(style blur: UIBlurEffect.Style = UIBlurEffect.Style.regular, closure: () -> UIView) { + public init( + style blur: UIBlurEffect.Style = UIBlurEffect.Style.regular, + closure: () -> UIView + ) { super.init(effect: UIBlurEffect(style: blur)) contentView.embed { @@ -39,9 +45,11 @@ public class BlurView: UIVisualEffectView { @available(iOS 13.0, *) public class VibrancyView: UIVisualEffectView { - public init(blurStyle blur: UIBlurEffect.Style = UIBlurEffect.Style.regular, - vibrancyStyle vibrancy: UIVibrancyEffectStyle = .fill, - closure: () -> UIView) { + public init( + blurStyle blur: UIBlurEffect.Style = UIBlurEffect.Style.regular, + vibrancyStyle vibrancy: UIVibrancyEffectStyle = .fill, + closure: () -> UIView + ) { super.init(effect: UIVibrancyEffect(blurEffect: UIBlurEffect(style: blur), style: vibrancy)) diff --git a/Sources/SwiftUIKit/Views/Image.swift b/Sources/SwiftUIKit/Views/Image.swift index 42d3374..0554966 100644 --- a/Sources/SwiftUIKit/Views/Image.swift +++ b/Sources/SwiftUIKit/Views/Image.swift @@ -13,13 +13,13 @@ public class Image: UIImageView { super.init(image: image) } - public init(_ color: UIColor) { + public init(color: UIColor) { super.init(frame: .zero) self.image = Image.image(fromColor: color) } - public init(_ name: String) { + public init(named name: String) { super.init(frame: .zero) guard let image = UIImage(named: name) else { diff --git a/Sources/SwiftUIKit/Views/List.swift b/Sources/SwiftUIKit/Views/List.swift index 63172f9..ed79ad2 100644 --- a/Sources/SwiftUIKit/Views/List.swift +++ b/Sources/SwiftUIKit/Views/List.swift @@ -16,9 +16,11 @@ public class List: UITableView { private var didSelectHandler: ((UIView) -> Void)? private var configureCell: ((UITableViewCell) -> Void)? - public init(defaultCellHeight: Float? = nil, - estimatedCellHeight: Float? = nil, - _ closure: () -> [UIView]) { + public init( + defaultCellHeight: Float? = nil, + estimatedCellHeight: Float? = nil, + _ closure: () -> [UIView] + ) { self.defaultCellHeight = defaultCellHeight self.estimatedCellHeight = estimatedCellHeight @@ -73,7 +75,7 @@ extension List: UITableViewDataSource { // Start LoadingViews if let view = cell.contentView.allSubviews.first(where: { $0 is LoadingView }), - let loadingView = view as? LoadingView { + let loadingView = view as? LoadingView { loadingView.start() } diff --git a/Sources/SwiftUIKit/Views/LoadingImage.swift b/Sources/SwiftUIKit/Views/LoadingImage.swift index 1091bd8..88d946b 100644 --- a/Sources/SwiftUIKit/Views/LoadingImage.swift +++ b/Sources/SwiftUIKit/Views/LoadingImage.swift @@ -10,13 +10,15 @@ import UIKit @available(iOS 9.0, *) public class LoadingImage: UIView { private var loadingTint: UIColor? - private var errorHandler: ((LoadingImage, Error?) -> Void)? + private var errorHandler: ((LoadingImage?, Error?) -> Void)? private var completionHandler: ((UIImage?) -> Void)? - public init(_ url: URL? = nil, - loadingTint: UIColor? = nil, - onErrorLoading: ((LoadingImage, Error?) -> Void)? = nil, - onCompletedLoading: ((UIImage?) -> Void)? = nil) { + public init( + url: URL? = nil, + loadingTint: UIColor? = nil, + onErrorLoading: ((LoadingImage?, Error?) -> Void)? = nil, + onCompletedLoading: ((UIImage?) -> Void)? = nil + ) { super.init(frame: .zero) @@ -30,8 +32,8 @@ public class LoadingImage: UIView { if let tint = loadingTint { $0.color = tint } - } - .start() + } + .start() } guard let url = url else { @@ -67,8 +69,8 @@ public class LoadingImage: UIView { if let tint = loadingTint { $0.color = tint } - } - .start() + } + .start() } guard let url = url else { @@ -81,11 +83,8 @@ public class LoadingImage: UIView { print("Image \(#function) Error!") print("Issue loading Image with url: \(url.absoluteString)") - if let self = self { - self.errorHandler?(self, error) - } else { - self?.update(color: .systemRed) - } + self?.update(color: .systemRed) + self?.errorHandler?(self, error) self?.completionHandler?(nil) return } @@ -93,12 +92,9 @@ public class LoadingImage: UIView { print("Image \(#function) Error!") print("Issue loading Image with url: \(url.absoluteString)") print("Error: Could not create UIImage from data") - - if let self = self { - self.errorHandler?(self, error) - } else { - self?.update(color: .systemRed) - } + + self?.update(color: .systemRed) + self?.errorHandler?(self, error) self?.completionHandler?(nil) return } @@ -123,7 +119,7 @@ public class LoadingImage: UIView { .embed { Image(image) .contentMode(self.contentMode) - } + } } } @@ -137,9 +133,9 @@ public class LoadingImage: UIView { } self.clear() .embed { - Image(color) + Image(color: color) .contentMode(self.contentMode) - } + } } } } diff --git a/Sources/SwiftUIKit/Views/Map.swift b/Sources/SwiftUIKit/Views/Map.swift index f32b1ff..1c6e621 100644 --- a/Sources/SwiftUIKit/Views/Map.swift +++ b/Sources/SwiftUIKit/Views/Map.swift @@ -9,488 +9,509 @@ import Foundation import MapKit public struct MapPoint { - public let latitude: Double - public let longitude: Double - public let title: String - public let subtitle: String - - public init(latitude: Double, longitude: Double, title: String, subtitle: String) { - self.latitude = latitude - self.longitude = longitude - self.title = title - self.subtitle = subtitle - } + public let latitude: Double + public let longitude: Double + public let title: String + public let subtitle: String + + public init( + latitude: Double, + longitude: Double, + title: String, + subtitle: String + ) { + self.latitude = latitude + self.longitude = longitude + self.title = title + self.subtitle = subtitle + } } public class Map: MKMapView { - - fileprivate var initialCoordinates: CLLocationCoordinate2D - - fileprivate var onFinishLoadingHandler: ((MKMapView) -> ())? = nil - - fileprivate var afterRegionChangeHandler: ((MKMapView) -> ())? = nil - - fileprivate var beforeRegionChangeHandler: ((MKMapView) -> ())? = nil - - fileprivate var annotationViewConfigurationHandler: ((MKAnnotationView?, MKAnnotation) -> (MKAnnotationView?))? = nil - - fileprivate var onAccessoryTapHandler: ((MKMapView, MKAnnotationView, UIControl) -> ())? = nil - - fileprivate var onAnnotationViewStateChangeHandler: ((MKMapView, MKAnnotationView, MKAnnotationView.DragState, MKAnnotationView.DragState) -> ())? = nil - - fileprivate var onAnnotationSelectHandler: ((MKMapView, MKAnnotationView) -> ())? = nil - - fileprivate var onAnnotationDeselectHandler: ((MKMapView, MKAnnotationView) -> ())? = nil - - fileprivate var annotationViewIdentifier: String? = nil - - public init(lat latitude: Double, - lon longitude: Double, - points: (() -> [MapPoint])? = nil) { - let coordinates = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) - - initialCoordinates = coordinates - - super.init(frame: .zero) - - let span = MKCoordinateSpan(latitudeDelta: region.span.latitudeDelta / 2, - longitudeDelta: region.span.longitudeDelta / 2) - - let region = MKCoordinateRegion(center: coordinates, span: span) - setRegion(region, animated: true) - - if let points = points { - add(points: points()) - } - - self.delegate = self - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + + fileprivate var initialCoordinates: CLLocationCoordinate2D + + fileprivate var onFinishLoadingHandler: ((MKMapView) -> ())? = nil + + fileprivate var afterRegionChangeHandler: ((MKMapView) -> ())? = nil + + fileprivate var beforeRegionChangeHandler: ((MKMapView) -> ())? = nil + + fileprivate var annotationViewConfigurationHandler: ((MKAnnotationView?, MKAnnotation) -> (MKAnnotationView?))? = nil + + fileprivate var onAccessoryTapHandler: ((MKMapView, MKAnnotationView, UIControl) -> ())? = nil + + fileprivate var onAnnotationViewStateChangeHandler: ((MKMapView, MKAnnotationView, MKAnnotationView.DragState, MKAnnotationView.DragState) -> ())? = nil + + fileprivate var onAnnotationSelectHandler: ((MKMapView, MKAnnotationView) -> ())? = nil + + fileprivate var onAnnotationDeselectHandler: ((MKMapView, MKAnnotationView) -> ())? = nil + + fileprivate var annotationViewIdentifier: String? = nil + + public init( + lat latitude: Double, + lon longitude: Double, + points: (() -> [MapPoint])? = nil + ) { + let coordinates = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) + + initialCoordinates = coordinates + + super.init(frame: .zero) + + let span = MKCoordinateSpan(latitudeDelta: region.span.latitudeDelta / 2, + longitudeDelta: region.span.longitudeDelta / 2) + + let region = MKCoordinateRegion(center: coordinates, span: span) + setRegion(region, animated: true) + + if let points = points { + add(points: points()) + } + + self.delegate = self + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } // MARK: - Initializers public extension Map { - convenience init(region: MKCoordinateRegion, - points: (() -> [MapPoint])? = nil) { - self.init(lat: region.center.latitude, - lon: region.center.longitude, - points: points) - } + convenience init( + region: MKCoordinateRegion, + points: (() -> [MapPoint])? = nil + ) { + self.init(lat: region.center.latitude, + lon: region.center.longitude, + points: points) + } } // MARK: - Accessing Map Properties public extension Map { - @discardableResult - func type(_ type: MKMapType) -> Self { - mapType = type - - return self - } - - @discardableResult - func zoomEnabled(_ value: Bool = true) -> Self { - isZoomEnabled = value - - return self - } - - @discardableResult - func scrollEnabled(_ value: Bool = true) -> Self { - isScrollEnabled = value - - return self - } - - @discardableResult - func pitchEnabled(_ value: Bool = true) -> Self { - isPitchEnabled = value - - return self - } - - @discardableResult - func rotateEnabled(_ value: Bool = true) -> Self { - isRotateEnabled = value - - return self - } - - /// Note: If delegate isn't its own class, modifiers based on delegate's methods will do nothing. - @discardableResult - func delegate(_ delegate: MKMapViewDelegate?) -> Self { - self.delegate = delegate ?? self - - return self - } + @discardableResult + func type(_ type: MKMapType) -> Self { + mapType = type + + return self + } + + @discardableResult + func zoomEnabled(_ value: Bool = true) -> Self { + isZoomEnabled = value + + return self + } + + @discardableResult + func scrollEnabled(_ value: Bool = true) -> Self { + isScrollEnabled = value + + return self + } + + @discardableResult + func pitchEnabled(_ value: Bool = true) -> Self { + isPitchEnabled = value + + return self + } + + @discardableResult + func rotateEnabled(_ value: Bool = true) -> Self { + isRotateEnabled = value + + return self + } + + /// Note: If delegate isn't its own class, modifiers based on delegate's methods will do nothing. + @discardableResult + func delegate(_ delegate: MKMapViewDelegate?) -> Self { + self.delegate = delegate ?? self + + return self + } } // MARK: - Manipulating the Visible Portion of the Map public extension Map { - @discardableResult - func zoom(_ multiplier: Double) -> Self { - let _center = initialCoordinates - let _span = MKCoordinateSpan(latitudeDelta: region.span.latitudeDelta / multiplier / 10, - longitudeDelta: region.span.longitudeDelta / multiplier / 10) - let _region = MKCoordinateRegion(center: _center, span: _span) - - setRegion(_region, animated: false) - return self - } - - @discardableResult - func visible(rect: MKMapRect, - animate: Bool = true, - edgePadding: UIEdgeInsets? = nil - ) -> Self { - if let padding = edgePadding { - setVisibleMapRect(rect, edgePadding: padding, animated: animate) - } else { - setVisibleMapRect(rect, animated: animate) - } - - return self - } - - /// Changes coordinates and span. - @discardableResult - func move(to region: MKCoordinateRegion, animate: Bool = true) -> Self { - initialCoordinates = region.center - setRegion(region, animated: animate) - - return self - } - - - /// Changes only coordinates. - @discardableResult - func move(to coordinates: CLLocationCoordinate2D, animate: Bool = true) -> Self { - let _region = MKCoordinateRegion(center: coordinates, span: region.span) - initialCoordinates = coordinates - setRegion(_region, animated: animate) - - return self - } - - @discardableResult - func center(_ center: CLLocationCoordinate2D, animated: Bool = true) -> Self { - setCenter(center, animated: animated) - - return self - } - - @discardableResult - func show(annotations: [MKAnnotation], animated: Bool = true) -> Self { - super.showAnnotations(annotations, animated: animated) - - return self - } - - @discardableResult - func show(annotations: MKAnnotation..., animated: Bool = true) -> Self { - super.showAnnotations(annotations, animated: animated) - - return self - } + @discardableResult + func zoom(_ multiplier: Double) -> Self { + let _center = initialCoordinates + let _span = MKCoordinateSpan(latitudeDelta: region.span.latitudeDelta / multiplier / 10, + longitudeDelta: region.span.longitudeDelta / multiplier / 10) + let _region = MKCoordinateRegion(center: _center, span: _span) + + setRegion(_region, animated: false) + return self + } + + @discardableResult + func visible(rect: MKMapRect, + animate: Bool = true, + edgePadding: UIEdgeInsets? = nil + ) -> Self { + if let padding = edgePadding { + setVisibleMapRect(rect, edgePadding: padding, animated: animate) + } else { + setVisibleMapRect(rect, animated: animate) + } + + return self + } + + /// Changes coordinates and span. + @discardableResult + func move(to region: MKCoordinateRegion, animate: Bool = true) -> Self { + initialCoordinates = region.center + setRegion(region, animated: animate) + + return self + } + + + /// Changes only coordinates. + @discardableResult + func move(to coordinates: CLLocationCoordinate2D, animate: Bool = true) -> Self { + let _region = MKCoordinateRegion(center: coordinates, span: region.span) + initialCoordinates = coordinates + setRegion(_region, animated: animate) + + return self + } + + @discardableResult + func center(_ center: CLLocationCoordinate2D, animated: Bool = true) -> Self { + setCenter(center, animated: animated) + + return self + } + + @discardableResult + func show(annotations: [MKAnnotation], animated: Bool = true) -> Self { + super.showAnnotations(annotations, animated: animated) + + return self + } + + @discardableResult + func show(annotations: MKAnnotation..., animated: Bool = true) -> Self { + super.showAnnotations(annotations, animated: animated) + + return self + } } // MARK: - Constraining the Map View @available(iOS 13.0, *) public extension Map { - @discardableResult - func camera(boundary: MKMapView.CameraBoundary?, animated: Bool = true) -> Self { - setCameraBoundary(boundary, animated: animated) - - return self - } - - @discardableResult - func set(cameraZoomRange: MKMapView.CameraZoomRange?, animated: Bool) -> Self { - super.setCameraZoomRange(cameraZoomRange, animated: animated) - - return self - } + @discardableResult + func camera(boundary: MKMapView.CameraBoundary?, animated: Bool = true) -> Self { + setCameraBoundary(boundary, animated: animated) + + return self + } + + @discardableResult + func set(cameraZoomRange: MKMapView.CameraZoomRange?, animated: Bool) -> Self { + super.setCameraZoomRange(cameraZoomRange, animated: animated) + + return self + } } // MARK: - Configuring the Map's Appearance public extension Map { - @discardableResult - func camera(_ camera: MKMapCamera, animated: Bool = true) -> Self { - setCamera(camera, animated: animated) - - return self - } - - @discardableResult - func showBuildings(_ bool: Bool) -> Self { - showsBuildings = bool - - return self - } + @discardableResult + func camera(_ camera: MKMapCamera, animated: Bool = true) -> Self { + setCamera(camera, animated: animated) + + return self + } + + @discardableResult + func showBuildings(_ bool: Bool) -> Self { + showsBuildings = bool + + return self + } } @available(iOS 13.0, *) public extension Map { - @discardableResult - func showCompass(_ bool: Bool) -> Self { - showsCompass = bool - - return self - } - - @discardableResult - func showScale(_ bool: Bool) -> Self { - showsScale = bool - - return self - } - - @discardableResult - func showTraffic(_ bool: Bool) -> Self { - showsTraffic = bool - - return self - } - - @discardableResult - func pointOfInterestFilter(filter: MKPointOfInterestFilter?) -> Self { - pointOfInterestFilter = filter - - return self - } + @discardableResult + func showCompass(_ bool: Bool) -> Self { + showsCompass = bool + + return self + } + + @discardableResult + func showScale(_ bool: Bool) -> Self { + showsScale = bool + + return self + } + + @discardableResult + func showTraffic(_ bool: Bool) -> Self { + showsTraffic = bool + + return self + } + + @discardableResult + func pointOfInterestFilter(filter: MKPointOfInterestFilter?) -> Self { + pointOfInterestFilter = filter + + return self + } } // MARK: - Displaying the User's Location public extension Map { - @discardableResult - func showUserLocation(_ bool: Bool) -> Self { - showsUserLocation = bool - - return self - } - - @discardableResult - func user(trackingMode: MKUserTrackingMode, animated: Bool = true) -> Self { - setUserTrackingMode(trackingMode, animated: animated) - - return self - } + @discardableResult + func showUserLocation(_ bool: Bool) -> Self { + showsUserLocation = bool + + return self + } + + @discardableResult + func user(trackingMode: MKUserTrackingMode, animated: Bool = true) -> Self { + setUserTrackingMode(trackingMode, animated: animated) + + return self + } } // MARK: - Managing Annotation Selections public extension Map { - @discardableResult - func select(annotation: MKAnnotation, animated: Bool = true) -> Self { - selectAnnotation(annotation, animated: animated) - - return self - } - - @discardableResult - func deselect(annotation: MKAnnotation, animated: Bool = true) -> Self { - deselectAnnotation(annotation, animated: animated) - - return self - } + @discardableResult + func select(annotation: MKAnnotation, animated: Bool = true) -> Self { + selectAnnotation(annotation, animated: animated) + + return self + } + + @discardableResult + func deselect(annotation: MKAnnotation, animated: Bool = true) -> Self { + deselectAnnotation(annotation, animated: animated) + + return self + } } // MARK: - Annotating the Map public extension Map { - @discardableResult - func remove(annotation: MKAnnotation) -> Self { - removeAnnotation(annotation) - - return self - } - - @discardableResult - func remove(annotations: [MKAnnotation]) -> Self { - removeAnnotations(annotations) - - return self - } - - @discardableResult - func add(annotation: MKAnnotation) -> Self { - addAnnotation(annotation) - - return self - } - - @discardableResult - func add(point: MapPoint) -> Self { - DispatchQueue.global().async { - let annotation = MKPointAnnotation() - - annotation.coordinate = CLLocationCoordinate2D(latitude: point.latitude, - longitude: point.longitude) - annotation.title = point.title - annotation.subtitle = point.subtitle - - DispatchQueue.main.async { - self.addAnnotation(annotation) - } - } - - return self - } - - @discardableResult - func add(annotations: [MKAnnotation]) -> Self { - addAnnotations(annotations) - - return self - } - - @discardableResult - func add(points: [MapPoint]) -> Self { - for point in points { - add(point: point) - } - - return self - } + @discardableResult + func remove(annotation: MKAnnotation) -> Self { + removeAnnotation(annotation) + + return self + } + + @discardableResult + func remove(annotations: [MKAnnotation]) -> Self { + removeAnnotations(annotations) + + return self + } + + @discardableResult + func add(annotation: MKAnnotation) -> Self { + addAnnotation(annotation) + + return self + } + + @discardableResult + func add(point: MapPoint) -> Self { + DispatchQueue.global().async { + let annotation = MKPointAnnotation() + + annotation.coordinate = CLLocationCoordinate2D(latitude: point.latitude, + longitude: point.longitude) + annotation.title = point.title + annotation.subtitle = point.subtitle + + DispatchQueue.main.async { + self.addAnnotation(annotation) + } + } + + return self + } + + @discardableResult + func add(annotations: [MKAnnotation]) -> Self { + addAnnotations(annotations) + + return self + } + + @discardableResult + func add(points: [MapPoint]) -> Self { + for point in points { + add(point: point) + } + + return self + } } // MARK: - Creating Annotation Views @available(iOS 11.0, *) public extension Map { - @discardableResult - func register(classes: [String: AnyClass?]) -> Self { - for (identifier, annotationClass) in classes { - register(annotationClass, forAnnotationViewWithReuseIdentifier: identifier) + @discardableResult + func register(classes: [String: AnyClass.Type]) -> Self { + for (identifier, annotationClass) in classes { + register(annotationClass, forAnnotationViewWithReuseIdentifier: identifier) + } + + return self } - - return self - } } // MARK: - Adjusting Map Regions and Rectangles public extension Map { - @discardableResult - func fitTo(region: MKCoordinateRegion) -> Self { - self.region = regionThatFits(region) - - return self - } - - @discardableResult - func fitTo(rect: MKMapRect, edgePadding: UIEdgeInsets? = nil) -> Self { - if let edgePadding = edgePadding { - mapRectThatFits(rect, edgePadding: edgePadding) - } else { - mapRectThatFits(rect) - } - - return self - } + @discardableResult + func fitTo(region: MKCoordinateRegion) -> Self { + self.region = regionThatFits(region) + + return self + } + + @discardableResult + func fitTo(rect: MKMapRect, edgePadding: UIEdgeInsets? = nil) -> Self { + if let edgePadding = edgePadding { + mapRectThatFits(rect, edgePadding: edgePadding) + } else { + mapRectThatFits(rect) + } + + return self + } } // MARK: - Delegate wrappers // If delegate isn't its own class, methods below will not execute. public extension Map { - @discardableResult - func onFinishLoading(_ handler: @escaping (MKMapView) -> ()) -> Self { - guard delegate === self else { return self } - onFinishLoadingHandler = handler - - return self - } - - @discardableResult - func afterRegionChange(_ handler: @escaping (MKMapView) -> ()) -> Self { - guard delegate === self else { return self } - afterRegionChangeHandler = handler - - return self - } - - @discardableResult - func beforeRegionChange(_ handler: @escaping (MKMapView) -> ()) -> Self { - guard delegate === self else { return self } - beforeRegionChangeHandler = handler - - return self - } - - @discardableResult - func configure(identifier: String?, _ annotationView: @escaping ((MKAnnotationView?, MKAnnotation) -> (MKAnnotationView?))) -> Self { - guard delegate === self else { return self } - annotationViewIdentifier = identifier - annotationViewConfigurationHandler = annotationView - - return self - } - - @discardableResult - func onAccessoryTap(_ handler: @escaping (MKMapView, MKAnnotationView, UIControl) -> ()) -> Self { - onAccessoryTapHandler = handler - - return self - } - - @discardableResult - func onAnnotationViewStateChange(_ handler: @escaping ((MKMapView, MKAnnotationView, MKAnnotationView.DragState, MKAnnotationView.DragState) -> ())) -> Self { - onAnnotationViewStateChangeHandler = handler - - return self - } - - @discardableResult - func onAnnotationSelect(_ handler: @escaping ((MKMapView, MKAnnotationView) -> ())) -> Self { - onAnnotationSelectHandler = handler - - return self - } - - @discardableResult - func onAnnotationDeselect(_ handler: @escaping ((MKMapView, MKAnnotationView) -> ())) -> Self { - onAnnotationDeselectHandler = handler - - return self - } + @discardableResult + func onFinishLoading(_ handler: @escaping (MKMapView) -> ()) -> Self { + guard delegate === self else { return self } + onFinishLoadingHandler = handler + + return self + } + + @discardableResult + func afterRegionChange(_ handler: @escaping (MKMapView) -> ()) -> Self { + guard delegate === self else { return self } + afterRegionChangeHandler = handler + + return self + } + + @discardableResult + func beforeRegionChange(_ handler: @escaping (MKMapView) -> ()) -> Self { + guard delegate === self else { return self } + beforeRegionChangeHandler = handler + + return self + } + + @discardableResult + func configure( + identifier: String?, + _ annotationView: @escaping ((MKAnnotationView?, MKAnnotation) -> (MKAnnotationView?)) + ) -> Self { + guard delegate === self else { return self } + annotationViewIdentifier = identifier + annotationViewConfigurationHandler = annotationView + + return self + } + + @discardableResult + func onAccessoryTap(_ handler: @escaping (MKMapView, MKAnnotationView, UIControl) -> ()) -> Self { + onAccessoryTapHandler = handler + + return self + } + + @discardableResult + func onAnnotationViewStateChange(_ handler: @escaping ((MKMapView, MKAnnotationView, MKAnnotationView.DragState, MKAnnotationView.DragState) -> ())) -> Self { + onAnnotationViewStateChangeHandler = handler + + return self + } + + @discardableResult + func onAnnotationSelect(_ handler: @escaping ((MKMapView, MKAnnotationView) -> ())) -> Self { + onAnnotationSelectHandler = handler + + return self + } + + @discardableResult + func onAnnotationDeselect(_ handler: @escaping ((MKMapView, MKAnnotationView) -> ())) -> Self { + onAnnotationDeselectHandler = handler + + return self + } } // MARK: - Delegation extension Map: MKMapViewDelegate { - public func mapViewDidFinishLoadingMap(_ mapView: MKMapView) { - onFinishLoadingHandler?(mapView) - } - - public func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) { - afterRegionChangeHandler?(mapView) - } - - public func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) { - beforeRegionChangeHandler?(mapView) - } - - public func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { - if let identifier = annotationViewIdentifier { - let annotationView = dequeueReusableAnnotationView(withIdentifier: identifier) - - return annotationViewConfigurationHandler?(annotationView, annotation) - } - - return annotationViewConfigurationHandler?(nil, annotation) - } - - public func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) { - onAccessoryTapHandler?(mapView, view, control) - } - - public func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, didChange newState: MKAnnotationView.DragState, fromOldState oldState: MKAnnotationView.DragState) { - onAnnotationViewStateChangeHandler?(mapView, view, newState, oldState) - } - - public func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) { - onAnnotationSelectHandler?(mapView, view) - } - - public func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) { - onAnnotationDeselectHandler?(mapView, view) - } + public func mapViewDidFinishLoadingMap(_ mapView: MKMapView) { + onFinishLoadingHandler?(mapView) + } + + public func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) { + afterRegionChangeHandler?(mapView) + } + + public func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) { + beforeRegionChangeHandler?(mapView) + } + + public func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { + if let identifier = annotationViewIdentifier { + let annotationView = dequeueReusableAnnotationView(withIdentifier: identifier) + + return annotationViewConfigurationHandler?(annotationView, annotation) + } + + return annotationViewConfigurationHandler?(nil, annotation) + } + + public func mapView( + _ mapView: MKMapView, + annotationView view: MKAnnotationView, + calloutAccessoryControlTapped control: UIControl + ) { + onAccessoryTapHandler?(mapView, view, control) + } + + public func mapView( + _ mapView: MKMapView, + annotationView view: MKAnnotationView, + didChange newState: MKAnnotationView.DragState, + fromOldState oldState: MKAnnotationView.DragState + ) { + onAnnotationViewStateChangeHandler?(mapView, view, newState, oldState) + } + + public func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) { + onAnnotationSelectHandler?(mapView, view) + } + + public func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) { + onAnnotationDeselectHandler?(mapView, view) + } } diff --git a/Sources/SwiftUIKit/Views/MultiLineField.swift b/Sources/SwiftUIKit/Views/MultiLineField.swift index d404ccf..6f13534 100644 --- a/Sources/SwiftUIKit/Views/MultiLineField.swift +++ b/Sources/SwiftUIKit/Views/MultiLineField.swift @@ -15,9 +15,7 @@ public class MultiLineField: UITextView { private var willInputUpdateHandler: WillValueChangeHandler? private var inputHandler: DidValueChangeHandler? - public init(value: String, - keyboardType type: UIKeyboardType) { - + public init(value: String, keyboardType type: UIKeyboardType) { super.init(frame: .zero, textContainer: nil) self.text = value @@ -47,7 +45,11 @@ public class MultiLineField: UITextView { @available(iOS 9.0, *) extension MultiLineField: UITextViewDelegate { - public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { + public func textView( + _ textView: UITextView, + shouldChangeTextIn range: NSRange, + replacementText text: String + ) -> Bool { let newValue = NSString(string: textView.text ?? "").replacingCharacters(in: range, with: text) return willInputUpdateHandler?(textView, newValue, text) ?? true diff --git a/Sources/SwiftUIKit/Views/NavButton.swift b/Sources/SwiftUIKit/Views/NavButton.swift index 67eca07..b0bb23e 100644 --- a/Sources/SwiftUIKit/Views/NavButton.swift +++ b/Sources/SwiftUIKit/Views/NavButton.swift @@ -12,41 +12,49 @@ public class NavButton: Button { private var destination: () -> UIViewController private var style: Navigate.NavigationStyle - public init(_ title: String, - tapHandler: (() -> Void)? = nil, - destination: @escaping () -> UIViewController, - style: Navigate.NavigationStyle, - titleColor: UIColor? = nil, - backgroundColor: UIColor? = nil) { + public init( + title: String, + tapHandler: (() -> Void)? = nil, + destination: @escaping () -> UIViewController, + style: Navigate.NavigationStyle, + titleColor: UIColor? = nil, + backgroundColor: UIColor? = nil + ) { self.destination = destination self.style = style - super.init(title, - titleColor: titleColor, - backgroundColor: backgroundColor, - forEvent: .touchUpInside) { - tapHandler?() - Navigate.shared.go(destination(), - style: style) - } + super.init( + title: title, + titleColor: titleColor, + backgroundColor: backgroundColor, + forEvent: .touchUpInside, + action: { + tapHandler?() + Navigate.shared.go(destination(), style: style) + } + ) } - public init(tapHandler: (() -> Void)? = nil, - destination: @escaping () -> UIViewController, - style: Navigate.NavigationStyle, - _ closure: () -> UIView) { + + public init( + tapHandler: (() -> Void)? = nil, + destination: @escaping () -> UIViewController, + style: Navigate.NavigationStyle, + labelView: () -> UIView + ) { self.destination = destination self.style = style - super.init(action: { - tapHandler?() - Navigate.shared.go(destination(), - style: style) - }, - forEvent: .touchUpInside, - closure) + super.init( + forEvent: .touchUpInside, + action: { + tapHandler?() + Navigate.shared.go(destination(), style: style) + }, + labelView: labelView + ) } required init?(coder: NSCoder) { diff --git a/Sources/SwiftUIKit/Views/ObservedView.swift b/Sources/SwiftUIKit/Views/ObservedView.swift new file mode 100644 index 0000000..014d1d1 --- /dev/null +++ b/Sources/SwiftUIKit/Views/ObservedView.swift @@ -0,0 +1,56 @@ +// +// ObservedView.swift +// +// +// Created by Zach Eriksen on 8/25/20. +// + +import E +import UIKit +import Chain +import Observation + +@available(iOS 9.0, *) +public class ObservedView: UIView where View: UIView { + private var observedValue: ObservedValue = ObservedValue() + + private var observedView: View + private var onChangeHandler: (Value?, View) -> Void + + public init( + view: View, + initialValue: Value?, + onChangeHandler: @escaping (_ newValue: Value?, _ view: View) -> Void + ) { + self.observedView = view + self.onChangeHandler = onChangeHandler + super.init(frame: .zero) + + observedValue.didChangeHandler = .complete( + .void { [weak self] in + self?.onChange() + } + ) + + if let initialValue = initialValue { + observedValue.update(value: initialValue) + } + + embed { + view + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @discardableResult + public func update(value: Value) -> Variable { + observedValue.update(value: value) + } + + private func onChange() { + onChangeHandler(observedValue.value, observedView) + } +} diff --git a/Sources/SwiftUIKit/Views/Slider.swift b/Sources/SwiftUIKit/Views/Slider.swift index 7feafa1..e398b06 100644 --- a/Sources/SwiftUIKit/Views/Slider.swift +++ b/Sources/SwiftUIKit/Views/Slider.swift @@ -11,10 +11,12 @@ import UIKit public class Slider: UISlider { private var valueChangedHandler: ((Float) -> Void)? - public init(value: Float, - from: Float, - to: Float, - _ valueChangedHandler: ((Float) -> Void)? = nil) { + public init( + value: Float, + from: Float, + to: Float, + valueChangedHandler: ((Float) -> Void)? = nil + ) { super.init(frame: .zero) diff --git a/Sources/SwiftUIKit/Views/Switch.swift b/Sources/SwiftUIKit/Views/Switch.swift index e3989d5..8f50e47 100644 --- a/Sources/SwiftUIKit/Views/Switch.swift +++ b/Sources/SwiftUIKit/Views/Switch.swift @@ -11,8 +11,10 @@ import UIKit public class Switch: UISwitch { private var toggleChangedHandler: ((Bool) -> Void)? - public init(isOn: Bool = false, - _ toggleChanged: ((Bool) -> Void)? = nil) { + public init( + isOn: Bool = false, + toggleChanged: ((Bool) -> Void)? = nil + ) { super.init(frame: .zero) self.isOn = isOn diff --git a/Sources/SwiftUIKit/Views/TableView.swift b/Sources/SwiftUIKit/Views/TableView.swift index e4222e8..a0122b5 100644 --- a/Sources/SwiftUIKit/Views/TableView.swift +++ b/Sources/SwiftUIKit/Views/TableView.swift @@ -31,7 +31,6 @@ public protocol CellConfigurable { public typealias TableViewCell = DataIdentifiable & CellConfigurable & CellUpdatable & UITableViewCell public typealias TableHeaderFooterViewHandler = (Int) -> UIView? -public typealias TableHeaderFooterTitleHandler = (Int) -> String? public typealias TableDidSelectIndexPathHandler = (IndexPath) -> Void public typealias TableHighlightIndexPathHandler = (IndexPath) -> Bool @@ -41,8 +40,6 @@ public class TableView: UITableView { fileprivate var headerViewForSection: TableHeaderFooterViewHandler? fileprivate var footerViewForSection: TableHeaderFooterViewHandler? - fileprivate var headerTitleForSection: TableHeaderFooterTitleHandler? - fileprivate var footerTitleForSection: TableHeaderFooterTitleHandler? fileprivate var didSelectRowAtIndexPath: TableDidSelectIndexPathHandler? fileprivate var shouldHighlightRowAtIndexPath: TableHighlightIndexPathHandler? fileprivate var canEditRowAtIndexPath: ((IndexPath) -> Bool)? @@ -66,8 +63,10 @@ public class TableView: UITableView { fileprivate var heightForHeaderInSection: ((Int) -> CGFloat)? fileprivate var heightForFooterInSection: ((Int) -> CGFloat)? - public init(initalData: [[CellDisplayable]] = [[CellDisplayable]](), - style: UITableView.Style = .plain) { + public init( + initalData: [[CellDisplayable]] = [[CellDisplayable]](), + style: UITableView.Style = .plain + ) { self.data = initalData super.init(frame: .zero, style: style) @@ -83,8 +82,10 @@ public class TableView: UITableView { @available(iOS 11.0, *) public extension TableView { @discardableResult - func update(shouldReloadData: Bool = false, - _ closure: ([[CellDisplayable]]) -> [[CellDisplayable]]) -> Self { + func update( + shouldReloadData: Bool = false, + _ closure: ([[CellDisplayable]]) -> [[CellDisplayable]] + ) -> Self { data = closure(data) if shouldReloadData { @@ -95,8 +96,10 @@ public extension TableView { } @discardableResult - func append(shouldReloadData: Bool = false, - _ closure: () -> [[CellDisplayable]]) -> Self { + func append( + shouldReloadData: Bool = false, + _ closure: () -> [[CellDisplayable]] + ) -> Self { data += closure() if shouldReloadData { @@ -126,7 +129,7 @@ extension TableView: UITableViewDataSource, UITableViewDelegate { } public func tableView(_ tableView: UITableView, indentationLevelForRowAt indexPath: IndexPath) -> Int { - indentationLevelForRowAtIndexPath?(indexPath) ?? 0 + indentationLevelForRowAtIndexPath?(indexPath) ?? 0 } public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { @@ -163,20 +166,12 @@ extension TableView: UITableViewDataSource, UITableViewDelegate { headerViewForSection?(section) } - public func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { - headerTitleForSection?(section) - } - // MARK: FooterForSection public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { footerViewForSection?(section) } - public func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? { - footerTitleForSection?(section) - } - // MARK: CanRowAt public func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { @@ -221,7 +216,11 @@ extension TableView: UITableViewDataSource, UITableViewDelegate { // MARK: Actions - public func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { + public func tableView( + _ tableView: UITableView, + commit editingStyle: UITableViewCell.EditingStyle, + forRowAt indexPath: IndexPath + ) { commitEditingStyleForRowAtIndexPath?(editingStyle, indexPath) } @@ -249,7 +248,11 @@ extension TableView: UITableViewDataSource, UITableViewDelegate { didUnhighlightRowAtIndexPath?(indexPath) } - public func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { + public func tableView( + _ tableView: UITableView, + moveRowAt sourceIndexPath: IndexPath, + to destinationIndexPath: IndexPath + ) { moveRowAtSourceIndexPathToDestinationIndexPath?(sourceIndexPath, destinationIndexPath) } @@ -303,20 +306,6 @@ public extension TableView { return self } - @discardableResult - func headerTitle(_ handler: @escaping TableHeaderFooterTitleHandler) -> Self { - headerTitleForSection = handler - - return self - } - - @discardableResult - func footerTitle(_ handler: @escaping TableHeaderFooterTitleHandler) -> Self { - footerTitleForSection = handler - - return self - } - @discardableResult func headerHeight(_ handler: @escaping (Int) -> CGFloat) -> Self { heightForHeaderInSection = handler diff --git a/Sources/SwiftUIKit/Views/Field.swift b/Sources/SwiftUIKit/Views/TextField.swift similarity index 79% rename from Sources/SwiftUIKit/Views/Field.swift rename to Sources/SwiftUIKit/Views/TextField.swift index aa3dc1c..4fefd59 100644 --- a/Sources/SwiftUIKit/Views/Field.swift +++ b/Sources/SwiftUIKit/Views/TextField.swift @@ -1,5 +1,5 @@ // -// Field.swift +// TextField.swift // // // Created by Zach Eriksen on 11/4/19. @@ -8,16 +8,18 @@ import UIKit @available(iOS 9.0, *) -public class Field: UITextField { +public class TextField: UITextField { public typealias WillValueChangeHandler = (_ sender: UITextField, _ newValue: String, _ input: String) -> Bool public typealias DidValueChangeHandler = (String) -> Void private var willInputUpdateHandler: WillValueChangeHandler? private var inputHandler: DidValueChangeHandler? - public init(value: String, - placeholder: String, - keyboardType type: UIKeyboardType) { + public init( + value: String, + placeholder: String, + keyboardType type: UIKeyboardType + ) { super.init(frame: .zero) @@ -53,8 +55,12 @@ public class Field: UITextField { } @available(iOS 9.0, *) -extension Field: UITextFieldDelegate { - public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { +extension TextField: UITextFieldDelegate { + public func textField( + _ textField: UITextField, + shouldChangeCharactersIn range: NSRange, + replacementString string: String + ) -> Bool { let newValue = NSString(string: textField.text ?? "").replacingCharacters(in: range, with: string) return willInputUpdateHandler?(textField, newValue, string) ?? true diff --git a/Sources/SwiftUIKit/Views/WebView.swift b/Sources/SwiftUIKit/Views/WebView.swift index 601bcc9..b40daed 100644 --- a/Sources/SwiftUIKit/Views/WebView.swift +++ b/Sources/SwiftUIKit/Views/WebView.swift @@ -22,10 +22,13 @@ public class WebView: WKWebView { @available(iOS 9.0, *) public extension WebView { - convenience init(baseURL: URL? = nil, _ htmlString: () -> String) { + convenience init( + baseURL: URL? = nil, + htmlString: () -> String + ) { self.init() - loadHTMLString(baseURL: baseURL, htmlString) + loadHTMLString(baseURL: baseURL, htmlString: htmlString) } convenience init(url: URL) { @@ -46,14 +49,25 @@ public extension WebView { loadFile(URL: URL, allowingReadAccessTo: URL) } - convenience init(data: Data, mimeType MIMEType: String, characterEncodingName: String, baseURL: URL) { + convenience init( + data: Data, + mimeType MIMEType: String, + characterEncodingName: String, + baseURL: URL + ) { self.init() - load(data: data, mimeType: MIMEType, characterEncodingName: characterEncodingName, baseURL: baseURL) + load(data: data, + mimeType: MIMEType, + characterEncodingName: characterEncodingName, + baseURL: baseURL) } @discardableResult - func loadHTMLString(baseURL: URL? = nil, _ htmlString: () -> String) -> Self { + func loadHTMLString( + baseURL: URL? = nil, + htmlString: () -> String + ) -> Self { loadHTMLString(htmlString(), baseURL: baseURL) return self @@ -81,8 +95,16 @@ public extension WebView { } @discardableResult - func load(data: Data, mimeType MIMEType: String, characterEncodingName: String, baseURL: URL) -> Self { - load(data, mimeType: MIMEType, characterEncodingName: characterEncodingName, baseURL: baseURL) + func load( + data: Data, + mimeType MIMEType: String, + characterEncodingName: String, + baseURL: URL + ) -> Self { + load(data, + mimeType: MIMEType, + characterEncodingName: characterEncodingName, + baseURL: baseURL) return self } diff --git a/Tests/SwiftUIKitTests/ADA/BasicADATests.swift b/Tests/SwiftUIKitTests/ADA/BasicADATests.swift index 02c55f4..bdb9906 100644 --- a/Tests/SwiftUIKitTests/ADA/BasicADATests.swift +++ b/Tests/SwiftUIKitTests/ADA/BasicADATests.swift @@ -26,7 +26,7 @@ final class BasicADATests: XCTestCase { } func testButtonADA() { - let button = Button("SomeString") { print("Hello") } + let button = Button(title: "SomeString") { print("Hello") } .accessibility(label: nil) XCTAssertEqual(button.accessibilityLabel, "SomeString") diff --git a/Tests/SwiftUIKitTests/Core/BasicSwiftUIKitTests.swift b/Tests/SwiftUIKitTests/Core/BasicSwiftUIKitTests.swift index 88c2e85..f87ca7d 100644 --- a/Tests/SwiftUIKitTests/Core/BasicSwiftUIKitTests.swift +++ b/Tests/SwiftUIKitTests/Core/BasicSwiftUIKitTests.swift @@ -7,7 +7,6 @@ import Foundation import XCTest -import Later @testable import SwiftUIKit @available(iOS 10.0, *) @@ -375,7 +374,7 @@ final class BasicSwiftUIKitTests: XCTestCase { let view = UIView().embed { UIView().vstack { [ - Image(.blue), + Image(color: .blue), Switch() ] } @@ -384,7 +383,7 @@ final class BasicSwiftUIKitTests: XCTestCase { let otherView = UIView().embed { VStack { [ - Image(.blue), + Image(color: .blue), Switch() ] } @@ -393,7 +392,7 @@ final class BasicSwiftUIKitTests: XCTestCase { let viewWithoutSwitch = UIView().embed { UIView().vstack { [ - Image(.blue) + Image(color: .blue) ] } } diff --git a/documentation/AttributedString.md b/documentation/AttributedString.md new file mode 100644 index 0000000..1ba4b06 --- /dev/null +++ b/documentation/AttributedString.md @@ -0,0 +1,5 @@ +# AttributedString + +``` swift +public typealias AttributedString = NSMutableAttributedString +``` diff --git a/documentation/AttributedStringKey.md b/documentation/AttributedStringKey.md new file mode 100644 index 0000000..7e2b49f --- /dev/null +++ b/documentation/AttributedStringKey.md @@ -0,0 +1,5 @@ +# AttributedStringKey + +``` swift +public typealias AttributedStringKey = NSAttributedString.Key +``` diff --git a/documentation/BarButton.md b/documentation/BarButton.md new file mode 100644 index 0000000..fcda0af --- /dev/null +++ b/documentation/BarButton.md @@ -0,0 +1,5 @@ +# BarButton + +``` swift +public typealias BarButton = UIBarButtonItem +``` diff --git a/documentation/BlurView.md b/documentation/BlurView.md new file mode 100644 index 0000000..754ebc3 --- /dev/null +++ b/documentation/BlurView.md @@ -0,0 +1,17 @@ +# BlurView + +``` swift +@available(iOS 10.0, *) public class BlurView: UIVisualEffectView +``` + +## Inheritance + +`UIVisualEffectView` + +## Initializers + +### `init(style:closure:)` + +``` swift +public init(style blur: UIBlurEffect.Style = UIBlurEffect.Style.regular, closure: () -> UIView) +``` diff --git a/documentation/Button.md b/documentation/Button.md new file mode 100644 index 0000000..49a5255 --- /dev/null +++ b/documentation/Button.md @@ -0,0 +1,31 @@ +# Button + +``` swift +@available(iOS 9.0, *) public class Button: UIButton +``` + +## Inheritance + +`UIButton` + +## Initializers + +### `init(title:titleColor:backgroundColor:forEvent:action:)` + +``` swift +public init(title: String, titleColor: UIColor? = nil, backgroundColor: UIColor? = nil, forEvent event: UIControl.Event = .touchUpInside, action: (() -> Void)? = nil) +``` + +### `init(forEvent:action:labelView:)` + +``` swift +public init(forEvent event: UIControl.Event = .touchUpInside, action: (() -> Void)? = nil, labelView: () -> UIView) +``` + +## Methods + +### `setAction(_:)` + +``` swift +@discardableResult public func setAction(_ action: (() -> Void)?) -> Self +``` diff --git a/documentation/CellConfigurable.md b/documentation/CellConfigurable.md new file mode 100644 index 0000000..47dbf65 --- /dev/null +++ b/documentation/CellConfigurable.md @@ -0,0 +1,13 @@ +# CellConfigurable + +``` swift +@available(iOS 11.0, *) public protocol CellConfigurable +``` + +## Requirements + +### configure(forData:​) + +``` swift +func configure(forData data: CellDisplayable) +``` diff --git a/documentation/CellDisplayable.md b/documentation/CellDisplayable.md new file mode 100644 index 0000000..672542e --- /dev/null +++ b/documentation/CellDisplayable.md @@ -0,0 +1,13 @@ +# CellDisplayable + +``` swift +@available(iOS 11.0, *) public protocol CellDisplayable +``` + +## Requirements + +### cellID + +``` swift +var cellID: String +``` diff --git a/documentation/CellUpdatable.md b/documentation/CellUpdatable.md new file mode 100644 index 0000000..10e9139 --- /dev/null +++ b/documentation/CellUpdatable.md @@ -0,0 +1,13 @@ +# CellUpdatable + +``` swift +@available(iOS 11.0, *) public protocol CellUpdatable +``` + +## Requirements + +### update(forData:​) + +``` swift +func update(forData data: CellDisplayable) +``` diff --git a/documentation/CollectionView.md b/documentation/CollectionView.md new file mode 100644 index 0000000..17b6878 --- /dev/null +++ b/documentation/CollectionView.md @@ -0,0 +1,489 @@ +# CollectionView + +``` swift +@available(iOS 11, *) public class CollectionView: UICollectionView +``` + +## Inheritance + +`UICollectionView`, `UICollectionViewDataSource`, `UICollectionViewDelegate`, `UICollectionViewDelegateFlowLayout` + +## Initializers + +### `init(initialData:)` + +``` swift +public init(initialData: [[CellDisplayable]] = [[CellDisplayable]]()) +``` + +## Properties + +### `data` + +``` swift +var data: [[CellDisplayable]] +``` + +## Methods + +### `set(delegateTo:)` + +Set a new delegate for CollectionView. +All modifiers depending on delegate will do nothing after calling that. + +``` swift +@discardableResult func set(delegateTo delegate: UICollectionViewDelegate) -> Self +``` + +### `set(dataSourceTo:)` + +Set a new delegate for CollectionView. +All modifiers depending on data source will do nothing after calling that. + +``` swift +@discardableResult func set(dataSourceTo dataSource: UICollectionViewDataSource) -> Self +``` + +### `set(layout:)` + +Set a new layout for collection view. + +``` swift +@discardableResult func set(layout: UICollectionViewLayout) -> Self +``` + +### `update(shouldReloadData:_:)` + +``` swift +@discardableResult func update(shouldReloadData: Bool = false, _ closure: ([[CellDisplayable]]) -> [[CellDisplayable]]) -> Self +``` + +### `append(shouldReloadData:_:)` + +``` swift +@discardableResult func append(shouldReloadData: Bool = false, _ closure: () -> [[CellDisplayable]]) -> Self +``` + +### `prefetchingEnabled(_:)` + +``` swift +@discardableResult func prefetchingEnabled(_ bool: Bool) -> Self +``` + +### `prefetchDataSource(_:)` + +``` swift +@discardableResult func prefetchDataSource(_ prefetchDataSource: () -> (UICollectionViewDataSourcePrefetching)) -> Self +``` + +### `register(cells:)` + +``` swift +@discardableResult func register(cells: [CollectionViewCell.Type]) -> Self +``` + +### `insertItems(at:)` + +``` swift +@discardableResult func insertItems(at indexPaths: [IndexPath]) -> Self +``` + +### `insertItem(at:)` + +``` swift +@discardableResult func insertItem(at indexPath: IndexPath) -> Self +``` + +### `moveItem(at:to:)` + +``` swift +@discardableResult func moveItem(at sourceIndexPath: IndexPath, to targetIndexPath: IndexPath) -> Self +``` + +### `moveItems(at:to:)` + +``` swift +@discardableResult func moveItems(at sourceIndexPaths: [IndexPath], to targetIndexPaths: [IndexPath]) -> Self +``` + +### `deleteItem(at:)` + +``` swift +@discardableResult func deleteItem(at indexPath: IndexPath) -> Self +``` + +### `deleteItems(at:)` + +``` swift +@discardableResult func deleteItems(at indexPaths: [IndexPath]) -> Self +``` + +### `scrollToItem(at:at:animated:)` + +``` swift +@discardableResult func scrollToItem(at indexPath: IndexPath, at position: UICollectionView.ScrollPosition, animated: Bool = true) -> Self +``` + +### `allowSelection(_:multiple:)` + +``` swift +@discardableResult func allowSelection(_ bool: Bool, multiple: Bool = false) -> Self +``` + +### `selectItem(at:animated:scrollPosition:)` + +``` swift +@discardableResult func selectItem(at indexPath: IndexPath, animated: Bool, scrollPosition: UICollectionView.ScrollPosition) -> Self +``` + +### `deselectItem(at:animated:)` + +``` swift +@discardableResult func deselectItem(at indexPath: IndexPath, animated: Bool) -> Self +``` + +### `insertSections(at:)` + +``` swift +@discardableResult func insertSections(at indexSet: IndexSet) -> Self +``` + +### `moveSection(from:to:)` + +``` swift +@discardableResult func moveSection(from section: Int, to newSection: Int) -> Self +``` + +### `deleteSections(at:)` + +``` swift +@discardableResult func deleteSections(at sections: IndexSet) -> Self +``` + +### `set(backgroundView:)` + +``` swift +@discardableResult func set(backgroundView: UIView) -> Self +``` + +### `setNumberOfItemsInSection(handler:)` + +``` swift +@discardableResult func setNumberOfItemsInSection(handler: @escaping ((UICollectionView, Int) -> Int)) -> Self +``` + +#### Parameters + + - handler: Contains actually declared collection view and given section, expects to return number of items for given section. + +### `configureCell(handler:)` + +``` swift +@discardableResult func configureCell(handler: @escaping ((UICollectionView, IndexPath) -> UICollectionViewCell)) -> Self +``` + +### `setSectionTitles(shouldReloadData:to:)` + +Set index titles for CollectionView + +``` swift +@discardableResult func setSectionTitles(shouldReloadData: Bool = false, to array: [String]) -> Self +``` + +#### Parameters + + - array: Used to provide titles for Collection View, order used is the same as the order of parameter. + +### `numberOfSections(in:)` + +``` swift +public func numberOfSections(in collectionView: UICollectionView) -> Int +``` + +### `collectionView(_:numberOfItemsInSection:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int +``` + +### `collectionView(_:cellForItemAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell +``` + +### `indexTitles(for:)` + +``` swift +public func indexTitles(for collectionView: UICollectionView) -> [String]? +``` + +### `collectionView(_:indexPathForIndexTitle:at:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, indexPathForIndexTitle title: String, at index: Int) -> IndexPath +``` + +### `shouldSelectItem(_:)` + +``` swift +@discardableResult func shouldSelectItem(_ handler: @escaping ((IndexPath) -> Bool)) -> Self +``` + +### `didSelectItemAt(_:)` + +``` swift +@discardableResult func didSelectItemAt(_ handler: @escaping ((IndexPath) -> ())) -> Self +``` + +### `shouldDeselectItemAt(_:)` + +``` swift +@discardableResult func shouldDeselectItemAt(_ handler: @escaping ((IndexPath) -> Bool)) -> Self +``` + +### `didDeselectItemAt(_:)` + +``` swift +@discardableResult func didDeselectItemAt(_ handler: @escaping ((IndexPath) -> ())) -> Self +``` + +### `shouldBeginMultipleSelectionInteractionAt(_:)` + +``` swift +@discardableResult func shouldBeginMultipleSelectionInteractionAt(_ handler: @escaping ((IndexPath) -> Bool)) -> Self +``` + +### `didBeginMultipleSelectionInteractionAt(_:)` + +``` swift +@discardableResult func didBeginMultipleSelectionInteractionAt(_ handler: @escaping ((IndexPath) -> ())) -> Self +``` + +### `didEndMultipleSelectionSelectionInteraction(_:)` + +``` swift +@discardableResult func didEndMultipleSelectionSelectionInteraction(_ handler: @escaping ((UICollectionView) -> ())) -> Self +``` + +### `shouldHighlightItemAt(_:)` + +``` swift +@discardableResult func shouldHighlightItemAt(_ handler: @escaping ((IndexPath) -> Bool)) -> Self +``` + +### `didHighlightItemAt(_:)` + +``` swift +@discardableResult func didHighlightItemAt(_ handler: @escaping ((IndexPath) -> ())) -> Self +``` + +### `didUnhighlightItemAt(_:)` + +``` swift +@discardableResult func didUnhighlightItemAt(_ handler: @escaping ((IndexPath) -> ())) -> Self +``` + +### `willDisplayCellHandlerFor(_:)` + +``` swift +@discardableResult func willDisplayCellHandlerFor(_ handler: @escaping ((CollectionViewCell, IndexPath) -> ())) -> Self +``` + +### `didEndDisplayingCellFor(_:)` + +``` swift +@discardableResult func didEndDisplayingCellFor(_ handler: @escaping ((CollectionViewCell, IndexPath) -> ())) -> Self +``` + +### `transitionLayoutFor(_:)` + +``` swift +@discardableResult func transitionLayoutFor(_ handler: @escaping (_ old: UICollectionViewLayout, _ new: UICollectionViewLayout) -> UICollectionViewTransitionLayout) -> Self +``` + +### `targetContentOffsetFor(_:)` + +``` swift +@discardableResult func targetContentOffsetFor(_ handler: @escaping (_ proposed: CGPoint) -> CGPoint) -> Self +``` + +### `targetIndexPathForMove(_:)` + +``` swift +@discardableResult func targetIndexPathForMove(_ handler: @escaping (_ from: IndexPath, _ to: IndexPath) -> IndexPath) -> Self +``` + +### `canFocusItemAt(_:)` + +``` swift +@discardableResult func canFocusItemAt(_ handler: @escaping (IndexPath) -> Bool) -> Self +``` + +### `collectionView(_:shouldSelectItemAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool +``` + +### `collectionView(_:didSelectItemAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) +``` + +### `collectionView(_:shouldDeselectItemAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, shouldDeselectItemAt indexPath: IndexPath) -> Bool +``` + +### `collectionView(_:didDeselectItemAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) +``` + +### `collectionView(_:shouldBeginMultipleSelectionInteractionAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, shouldBeginMultipleSelectionInteractionAt indexPath: IndexPath) -> Bool +``` + +### `collectionView(_:didBeginMultipleSelectionInteractionAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, didBeginMultipleSelectionInteractionAt indexPath: IndexPath) +``` + +### `collectionViewDidEndMultipleSelectionInteraction(_:)` + +``` swift +public func collectionViewDidEndMultipleSelectionInteraction(_ collectionView: UICollectionView) +``` + +### `collectionView(_:shouldHighlightItemAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool +``` + +### `collectionView(_:didHighlightItemAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) +``` + +### `collectionView(_:didUnhighlightItemAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) +``` + +### `collectionView(_:willDisplay:forItemAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) +``` + +### `collectionView(_:didEndDisplaying:forItemAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) +``` + +### `collectionView(_:transitionLayoutForOldLayout:newLayout:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, transitionLayoutForOldLayout fromLayout: UICollectionViewLayout, newLayout toLayout: UICollectionViewLayout) -> UICollectionViewTransitionLayout +``` + +### `collectionView(_:targetContentOffsetForProposedContentOffset:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, targetContentOffsetForProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint +``` + +### `collectionView(_:targetIndexPathForMoveFromItemAt:toProposedIndexPath:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath +``` + +### `collectionView(_:canFocusItemAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, canFocusItemAt indexPath: IndexPath) -> Bool +``` + +### `layoutSizeForItem(_:)` + +``` swift +@discardableResult func layoutSizeForItem(_ handler: @escaping ((UICollectionViewLayout, IndexPath) -> CGSize)) -> Self +``` + +### `sectionInsets(shouldUpdate:insets:)` + +``` swift +@discardableResult func sectionInsets(shouldUpdate: Bool = true, insets: [UIEdgeInsets]) -> Self +``` + +### `minimumLineSpacing(shouldUpdate:forSections:)` + +``` swift +@discardableResult func minimumLineSpacing(shouldUpdate: Bool = true, forSections spacings: [CGFloat]) -> Self +``` + +### `minimumInteritemSpacing(shouldUpdate:forSections:)` + +``` swift +@discardableResult func minimumInteritemSpacing(shouldUpdate: Bool = true, forSections spacings: [CGFloat]) -> Self +``` + +### `headerSize(shouldUpdate:forSections:)` + +``` swift +@discardableResult func headerSize(shouldUpdate: Bool = true, forSections sizes: [CGSize]) -> Self +``` + +### `footerSize(shouldUpdate:forSections:)` + +``` swift +@discardableResult func footerSize(shouldUpdate: Bool = true, forSections sizes: [CGSize]) -> Self +``` + +### `collectionView(_:layout:sizeForItemAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize +``` + +### `collectionView(_:layout:insetForSectionAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets +``` + +### `collectionView(_:layout:minimumLineSpacingForSectionAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat +``` + +### `collectionView(_:layout:minimumInteritemSpacingForSectionAt:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat +``` + +### `collectionView(_:layout:referenceSizeForHeaderInSection:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize +``` + +### `collectionView(_:layout:referenceSizeForFooterInSection:)` + +``` swift +public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize +``` diff --git a/documentation/CollectionViewCell.md b/documentation/CollectionViewCell.md new file mode 100644 index 0000000..23ce3bd --- /dev/null +++ b/documentation/CollectionViewCell.md @@ -0,0 +1,5 @@ +# CollectionViewCell + +``` swift +@available(iOS 11.0, *) public typealias CollectionViewCell = DataIdentifiable & CellConfigurable & CellUpdatable & UICollectionViewCell +``` diff --git a/documentation/ContainerView.md b/documentation/ContainerView.md new file mode 100644 index 0000000..85307c5 --- /dev/null +++ b/documentation/ContainerView.md @@ -0,0 +1,17 @@ +# ContainerView + +``` swift +@available(iOS 9.0, *) public class ContainerView: UIView +``` + +## Inheritance + +`UIView` + +## Initializers + +### `init(parent:child:)` + +``` swift +public init(parent: UIViewController, child: () -> UIViewController) +``` diff --git a/documentation/DataIdentifiable.md b/documentation/DataIdentifiable.md new file mode 100644 index 0000000..1b915f9 --- /dev/null +++ b/documentation/DataIdentifiable.md @@ -0,0 +1,13 @@ +# DataIdentifiable + +``` swift +@available(iOS 11.0, *) public protocol DataIdentifiable +``` + +## Requirements + +### ID + +``` swift +var ID: String +``` diff --git a/documentation/Divider.md b/documentation/Divider.md new file mode 100644 index 0000000..4825b65 --- /dev/null +++ b/documentation/Divider.md @@ -0,0 +1,17 @@ +# Divider + +``` swift +@available(iOS 9.0, *) public class Divider: UIView +``` + +## Inheritance + +`UIView` + +## Initializers + +### `init(_:color:)` + +``` swift +public init(_ axis: NSLayoutConstraint.Axis = .horizontal, color: UIColor? = .systemGray) +``` diff --git a/documentation/EffectView.md b/documentation/EffectView.md new file mode 100644 index 0000000..ad15a1c --- /dev/null +++ b/documentation/EffectView.md @@ -0,0 +1,17 @@ +# EffectView + +``` swift +@available(iOS 9.0, *) public class EffectView: UIVisualEffectView +``` + +## Inheritance + +`UIVisualEffectView` + +## Initializers + +### `init(for:closure:)` + +``` swift +public init(for effect: UIVisualEffect? = nil, closure: () -> UIView) +``` diff --git a/documentation/HScroll.md b/documentation/HScroll.md new file mode 100644 index 0000000..37a8084 --- /dev/null +++ b/documentation/HScroll.md @@ -0,0 +1,17 @@ +# HScroll + +``` swift +@available(iOS 9.0, *) public class HScroll: UIView +``` + +## Inheritance + +`UIView` + +## Initializers + +### `init(withPadding:_:)` + +``` swift +public init(withPadding padding: Float = 0, _ closure: () -> UIView) +``` diff --git a/documentation/HStack.md b/documentation/HStack.md new file mode 100644 index 0000000..fe321b5 --- /dev/null +++ b/documentation/HStack.md @@ -0,0 +1,53 @@ +# HStack + +Horizontal StackView + +``` swift +@available(iOS 9.0, *) public class HStack: UIView +``` + +## Inheritance + +`UIView` + +## Initializers + +### `init(withSpacing:padding:alignment:distribution:_:)` + +Create a HStack + +``` swift +public init(withSpacing spacing: Float = 0, padding: Float = 0, alignment: UIStackView.Alignment = .fill, distribution: UIStackView.Distribution = .fill, _ closure: () -> [UIView]) +``` + +#### Parameters + + - withSpacing: The amount of spacing between each child view + - padding: The amount of space between this view and its parent view + - alignment: The layout of arranged views perpendicular to the stack view’s axis (source: UIStackView.Alignment) + - distribution: The layout that defines the size and position of the arranged views along the stack view’s axis (source: UIStackView.Distribution) + - closure: A trailing closure that accepts an array of views + +### `init(withSpacing:padding:alignment:distribution:_:)` + +Create a HStack that accepts an array of UIView? + +``` swift +public init(withSpacing spacing: Float = 0, padding: Float = 0, alignment: UIStackView.Alignment = .fill, distribution: UIStackView.Distribution = .fill, _ closure: () -> [UIView?]) +``` + +#### Parameters + + - withSpacing: The amount of spacing between each child view + - padding: The amount of space between this view and its parent view + - alignment: The layout of arranged views perpendicular to the stack view’s axis (source: UIStackView.Alignment) + - distribution: The layout that defines the size and position of the arranged views along the stack view’s axis (source: UIStackView.Distribution) + - closure: A trailing closure that accepts an array of optional views + +## Methods + +### `update(views:)` + +``` swift +public func update(views closure: (inout [UIView]) -> Void) -> Self +``` diff --git a/documentation/Home.md b/documentation/Home.md new file mode 100644 index 0000000..7bfc375 --- /dev/null +++ b/documentation/Home.md @@ -0,0 +1,61 @@ +# Types + + - [HScroll](/HScroll) + - [HStack](/HStack): + Horizontal StackView + - [SafeAreaView](/SafeAreaView): + A View that respects the SafeArea + - [VScroll](/VScroll) + - [VStack](/VStack): + Vertical StackView + - [ZStack](/ZStack): + ZStack: + A view which stacks its children views in order + - [Padding](/Padding) + - [ViewController](/ViewController) + - [Navigate](/Navigate) + - [Navigate.NavigationStyle](/Navigate_NavigationStyle) + - [Navigate.ToastStyle](/Navigate_ToastStyle) + - [Button](/Button) + - [CollectionView](/CollectionView) + - [ContainerView](/ContainerView) + - [Divider](/Divider) + - [EffectView](/EffectView) + - [BlurView](/BlurView) + - [VibrancyView](/VibrancyView) + - [Image](/Image) + - [Label](/Label) + - [List](/List) + - [LoadingImage](/LoadingImage) + - [LoadingView](/LoadingView) + - [MapPoint](/MapPoint) + - [Map](/Map) + - [MultiLineField](/MultiLineField) + - [NavButton](/NavButton) + - [ObservedView](/ObservedView) + - [ScrollView](/ScrollView) + - [Slider](/Slider) + - [Spacer](/Spacer) + - [Switch](/Switch) + - [TableView](/TableView) + - [TextField](/TextField) + - [WebView](/WebView) + +# Protocols + + - [CellDisplayable](/CellDisplayable) + - [DataIdentifiable](/DataIdentifiable) + - [CellUpdatable](/CellUpdatable) + - [CellConfigurable](/CellConfigurable) + +# Global Typealiases + + - [AttributedString](/AttributedString) + - [AttributedStringKey](/AttributedStringKey) + - [StringAttributes](/StringAttributes) + - [BarButton](/BarButton) + - [CollectionViewCell](/CollectionViewCell) + - [TableViewCell](/TableViewCell) + - [TableHeaderFooterViewHandler](/TableHeaderFooterViewHandler) + - [TableDidSelectIndexPathHandler](/TableDidSelectIndexPathHandler) + - [TableHighlightIndexPathHandler](/TableHighlightIndexPathHandler) diff --git a/documentation/Image.md b/documentation/Image.md new file mode 100644 index 0000000..a416ec0 --- /dev/null +++ b/documentation/Image.md @@ -0,0 +1,37 @@ +# Image + +``` swift +@available(iOS 9.0, *) public class Image: UIImageView +``` + +## Inheritance + +`UIImageView` + +## Initializers + +### `init(_:)` + +``` swift +public init(_ image: UIImage) +``` + +### `init(color:)` + +``` swift +public init(color: UIColor) +``` + +### `init(named:)` + +``` swift +public init(named name: String) +``` + +## Methods + +### `contentMode(_:)` + +``` swift +@discardableResult public func contentMode(_ mode: UIView.ContentMode) -> Self +``` diff --git a/documentation/Label.md b/documentation/Label.md new file mode 100644 index 0000000..a9c9284 --- /dev/null +++ b/documentation/Label.md @@ -0,0 +1,127 @@ +# Label + +``` swift +@available(iOS 9.0, *) public class Label: UILabel +``` + +## Inheritance + +`UILabel` + +## Initializers + +### `init(_:)` + +``` swift +public init(_ text: String) +``` + +### `init(_:)` + +``` swift +public init(_ attributedText: AttributedString) +``` + +## Methods + +### `number(ofLines:)` + +``` swift +@discardableResult public func number(ofLines lines: Int) -> Self +``` + +### `font(_:)` + +``` swift +@discardableResult public func font(_ font: UIFont) -> Self +``` + +### `font(_:)` + +``` swift +@discardableResult public func font(_ textStyle: UIFont.TextStyle) -> Self +``` + +### `hideIfBlank()` + +``` swift +@discardableResult public func hideIfBlank() -> Self +``` + +### `apply(attributes:)` + +``` swift +@discardableResult public func apply(attributes: StringAttributes) -> Self +``` + +### `apply(attributes:range:)` + +``` swift +@discardableResult public func apply(attributes: StringAttributes, range: ClosedRange) -> Self +``` + +### `text(alignment:)` + +``` swift +@discardableResult public func text(alignment: NSTextAlignment) -> Self +``` + +### `text(color:)` + +``` swift +@discardableResult public func text(color: UIColor) -> Self +``` + +### `title1(_:)` + +``` swift +class func title1(_ text: String) -> Label +``` + +### `title2(_:)` + +``` swift +class func title2(_ text: String) -> Label +``` + +### `title3(_:)` + +``` swift +class func title3(_ text: String) -> Label +``` + +### `headline(_:)` + +``` swift +class func headline(_ text: String) -> Label +``` + +### `subheadline(_:)` + +``` swift +class func subheadline(_ text: String) -> Label +``` + +### `body(_:)` + +``` swift +class func body(_ text: String) -> Label +``` + +### `callout(_:)` + +``` swift +class func callout(_ text: String) -> Label +``` + +### `caption1(_:)` + +``` swift +class func caption1(_ text: String) -> Label +``` + +### `caption2(_:)` + +``` swift +class func caption2(_ text: String) -> Label +``` diff --git a/documentation/List.md b/documentation/List.md new file mode 100644 index 0000000..c94b1d3 --- /dev/null +++ b/documentation/List.md @@ -0,0 +1,67 @@ +# List + +``` swift +@available(iOS 9.0, *) public class List: UITableView +``` + +## Inheritance + +`UITableView`, `UITableViewDataSource`, `UITableViewDelegate` + +## Initializers + +### `init(defaultCellHeight:estimatedCellHeight:_:)` + +``` swift +public init(defaultCellHeight: Float? = nil, estimatedCellHeight: Float? = nil, _ closure: () -> [UIView]) +``` + +## Methods + +### `didSelectHandler(_:)` + +``` swift +@discardableResult func didSelectHandler(_ action: @escaping (UIView) -> Void) -> Self +``` + +### `configureCell(_:)` + +``` swift +@discardableResult func configureCell(_ action: @escaping (UITableViewCell) -> Void) -> Self +``` + +### `numberOfSections(in:)` + +``` swift +public func numberOfSections(in tableView: UITableView) -> Int +``` + +### `tableView(_:numberOfRowsInSection:)` + +``` swift +public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int +``` + +### `tableView(_:cellForRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell +``` + +### `tableView(_:heightForRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat +``` + +### `tableView(_:estimatedHeightForRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat +``` + +### `tableView(_:didSelectRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) +``` diff --git a/documentation/LoadingImage.md b/documentation/LoadingImage.md new file mode 100644 index 0000000..c222387 --- /dev/null +++ b/documentation/LoadingImage.md @@ -0,0 +1,43 @@ +# LoadingImage + +``` swift +@available(iOS 9.0, *) public class LoadingImage: UIView +``` + +## Inheritance + +`UIView` + +## Initializers + +### `init(url:loadingTint:onErrorLoading:onCompletedLoading:)` + +``` swift +public init(url: URL? = nil, loadingTint: UIColor? = nil, onErrorLoading: ((LoadingImage?, Error?) -> Void)? = nil, onCompletedLoading: ((UIImage?) -> Void)? = nil) +``` + +## Methods + +### `contentMode(_:)` + +``` swift +@discardableResult public func contentMode(_ mode: UIView.ContentMode) -> Self +``` + +### `onImageLoaded(_:)` + +``` swift +@discardableResult public func onImageLoaded(_ handler: @escaping (UIImage?) -> Void) -> Self +``` + +### `load(url:)` + +``` swift +@discardableResult public func load(url: URL?) -> Self +``` + +### `update(image:)` + +``` swift +public func update(image: UIImage) +``` diff --git a/documentation/LoadingView.md b/documentation/LoadingView.md new file mode 100644 index 0000000..fc3afcc --- /dev/null +++ b/documentation/LoadingView.md @@ -0,0 +1,43 @@ +# LoadingView + +``` swift +@available(iOS 9.0, *) public class LoadingView: UIActivityIndicatorView +``` + +## Inheritance + +`UIActivityIndicatorView` + +## Initializers + +### `init(forStyle:)` + +``` swift +public init(forStyle style: UIActivityIndicatorView.Style? = nil) +``` + +## Methods + +### `start()` + +``` swift +@discardableResult func start() -> Self +``` + +### `stop()` + +``` swift +@discardableResult func stop() -> Self +``` + +### `play(_:)` + +``` swift +@discardableResult func play(_ ifTrue: () -> Bool) -> Self +``` + +### `color(_:)` + +``` swift +@discardableResult func color(_ color: UIColor) -> Self +``` diff --git a/documentation/Map.md b/documentation/Map.md new file mode 100644 index 0000000..6fc0c04 --- /dev/null +++ b/documentation/Map.md @@ -0,0 +1,331 @@ +# Map + +``` swift +public class Map: MKMapView +``` + +## Inheritance + +`MKMapView`, `MKMapViewDelegate` + +## Initializers + +### `init(lat:lon:points:)` + +``` swift +public init(lat latitude: Double, lon longitude: Double, points: (() -> [MapPoint])? = nil) +``` + +### `init(region:points:)` + +``` swift +convenience init(region: MKCoordinateRegion, points: (() -> [MapPoint])? = nil) +``` + +## Methods + +### `type(_:)` + +``` swift +@discardableResult func type(_ type: MKMapType) -> Self +``` + +### `zoomEnabled(_:)` + +``` swift +@discardableResult func zoomEnabled(_ value: Bool = true) -> Self +``` + +### `scrollEnabled(_:)` + +``` swift +@discardableResult func scrollEnabled(_ value: Bool = true) -> Self +``` + +### `pitchEnabled(_:)` + +``` swift +@discardableResult func pitchEnabled(_ value: Bool = true) -> Self +``` + +### `rotateEnabled(_:)` + +``` swift +@discardableResult func rotateEnabled(_ value: Bool = true) -> Self +``` + +### `delegate(_:)` + +Note:​ If delegate isn't its own class, modifiers based on delegate's methods will do nothing. + +``` swift +@discardableResult func delegate(_ delegate: MKMapViewDelegate?) -> Self +``` + +### `zoom(_:)` + +``` swift +@discardableResult func zoom(_ multiplier: Double) -> Self +``` + +### `visible(rect:animate:edgePadding:)` + +``` swift +@discardableResult func visible(rect: MKMapRect, animate: Bool = true, edgePadding: UIEdgeInsets? = nil) -> Self +``` + +### `move(to:animate:)` + +Changes coordinates and span. + +``` swift +@discardableResult func move(to region: MKCoordinateRegion, animate: Bool = true) -> Self +``` + +### `move(to:animate:)` + +Changes only coordinates. + +``` swift +@discardableResult func move(to coordinates: CLLocationCoordinate2D, animate: Bool = true) -> Self +``` + +### `center(_:animated:)` + +``` swift +@discardableResult func center(_ center: CLLocationCoordinate2D, animated: Bool = true) -> Self +``` + +### `show(annotations:animated:)` + +``` swift +@discardableResult func show(annotations: [MKAnnotation], animated: Bool = true) -> Self +``` + +### `show(annotations:animated:)` + +``` swift +@discardableResult func show(annotations: MKAnnotation, animated: Bool = true) -> Self +``` + +### `camera(boundary:animated:)` + +``` swift +@discardableResult func camera(boundary: MKMapView.CameraBoundary?, animated: Bool = true) -> Self +``` + +### `set(cameraZoomRange:animated:)` + +``` swift +@discardableResult func set(cameraZoomRange: MKMapView.CameraZoomRange?, animated: Bool) -> Self +``` + +### `camera(_:animated:)` + +``` swift +@discardableResult func camera(_ camera: MKMapCamera, animated: Bool = true) -> Self +``` + +### `showBuildings(_:)` + +``` swift +@discardableResult func showBuildings(_ bool: Bool) -> Self +``` + +### `showCompass(_:)` + +``` swift +@discardableResult func showCompass(_ bool: Bool) -> Self +``` + +### `showScale(_:)` + +``` swift +@discardableResult func showScale(_ bool: Bool) -> Self +``` + +### `showTraffic(_:)` + +``` swift +@discardableResult func showTraffic(_ bool: Bool) -> Self +``` + +### `pointOfInterestFilter(filter:)` + +``` swift +@discardableResult func pointOfInterestFilter(filter: MKPointOfInterestFilter?) -> Self +``` + +### `showUserLocation(_:)` + +``` swift +@discardableResult func showUserLocation(_ bool: Bool) -> Self +``` + +### `user(trackingMode:animated:)` + +``` swift +@discardableResult func user(trackingMode: MKUserTrackingMode, animated: Bool = true) -> Self +``` + +### `select(annotation:animated:)` + +``` swift +@discardableResult func select(annotation: MKAnnotation, animated: Bool = true) -> Self +``` + +### `deselect(annotation:animated:)` + +``` swift +@discardableResult func deselect(annotation: MKAnnotation, animated: Bool = true) -> Self +``` + +### `remove(annotation:)` + +``` swift +@discardableResult func remove(annotation: MKAnnotation) -> Self +``` + +### `remove(annotations:)` + +``` swift +@discardableResult func remove(annotations: [MKAnnotation]) -> Self +``` + +### `add(annotation:)` + +``` swift +@discardableResult func add(annotation: MKAnnotation) -> Self +``` + +### `add(point:)` + +``` swift +@discardableResult func add(point: MapPoint) -> Self +``` + +### `add(annotations:)` + +``` swift +@discardableResult func add(annotations: [MKAnnotation]) -> Self +``` + +### `add(points:)` + +``` swift +@discardableResult func add(points: [MapPoint]) -> Self +``` + +### `register(classes:)` + +``` swift +@discardableResult func register(classes: [String: AnyClass.Type]) -> Self +``` + +### `fitTo(region:)` + +``` swift +@discardableResult func fitTo(region: MKCoordinateRegion) -> Self +``` + +### `fitTo(rect:edgePadding:)` + +``` swift +@discardableResult func fitTo(rect: MKMapRect, edgePadding: UIEdgeInsets? = nil) -> Self +``` + +### `onFinishLoading(_:)` + +``` swift +@discardableResult func onFinishLoading(_ handler: @escaping (MKMapView) -> ()) -> Self +``` + +### `afterRegionChange(_:)` + +``` swift +@discardableResult func afterRegionChange(_ handler: @escaping (MKMapView) -> ()) -> Self +``` + +### `beforeRegionChange(_:)` + +``` swift +@discardableResult func beforeRegionChange(_ handler: @escaping (MKMapView) -> ()) -> Self +``` + +### `configure(identifier:_:)` + +``` swift +@discardableResult func configure(identifier: String?, _ annotationView: @escaping ((MKAnnotationView?, MKAnnotation) -> (MKAnnotationView?))) -> Self +``` + +### `onAccessoryTap(_:)` + +``` swift +@discardableResult func onAccessoryTap(_ handler: @escaping (MKMapView, MKAnnotationView, UIControl) -> ()) -> Self +``` + +### `onAnnotationViewStateChange(_:)` + +``` swift +@discardableResult func onAnnotationViewStateChange(_ handler: @escaping ((MKMapView, MKAnnotationView, MKAnnotationView.DragState, MKAnnotationView.DragState) -> ())) -> Self +``` + +### `onAnnotationSelect(_:)` + +``` swift +@discardableResult func onAnnotationSelect(_ handler: @escaping ((MKMapView, MKAnnotationView) -> ())) -> Self +``` + +### `onAnnotationDeselect(_:)` + +``` swift +@discardableResult func onAnnotationDeselect(_ handler: @escaping ((MKMapView, MKAnnotationView) -> ())) -> Self +``` + +### `mapViewDidFinishLoadingMap(_:)` + +``` swift +public func mapViewDidFinishLoadingMap(_ mapView: MKMapView) +``` + +### `mapView(_:regionDidChangeAnimated:)` + +``` swift +public func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) +``` + +### `mapView(_:regionWillChangeAnimated:)` + +``` swift +public func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) +``` + +### `mapView(_:viewFor:)` + +``` swift +public func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? +``` + +### `mapView(_:annotationView:calloutAccessoryControlTapped:)` + +``` swift +public func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) +``` + +### `mapView(_:annotationView:didChange:fromOldState:)` + +``` swift +public func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, didChange newState: MKAnnotationView.DragState, fromOldState oldState: MKAnnotationView.DragState) +``` + +### `mapView(_:didSelect:)` + +``` swift +public func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) +``` + +### `mapView(_:didDeselect:)` + +``` swift +public func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) +``` diff --git a/documentation/MapPoint.md b/documentation/MapPoint.md new file mode 100644 index 0000000..a666908 --- /dev/null +++ b/documentation/MapPoint.md @@ -0,0 +1,39 @@ +# MapPoint + +``` swift +public struct MapPoint +``` + +## Initializers + +### `init(latitude:longitude:title:subtitle:)` + +``` swift +public init(latitude: Double, longitude: Double, title: String, subtitle: String) +``` + +## Properties + +### `latitude` + +``` swift +let latitude: Double +``` + +### `longitude` + +``` swift +let longitude: Double +``` + +### `title` + +``` swift +let title: String +``` + +### `subtitle` + +``` swift +let subtitle: String +``` diff --git a/documentation/MultiLineField.md b/documentation/MultiLineField.md new file mode 100644 index 0000000..f849a2c --- /dev/null +++ b/documentation/MultiLineField.md @@ -0,0 +1,57 @@ +# MultiLineField + +``` swift +@available(iOS 9.0, *) public class MultiLineField: UITextView +``` + +## Inheritance + +`UITextView`, `UITextViewDelegate` + +## Nested Type Aliases + +### `WillValueChangeHandler` + +``` swift +public typealias WillValueChangeHandler = (_ sender: UITextView, _ newValue: String, _ input: String) -> Bool +``` + +### `DidValueChangeHandler` + +``` swift +public typealias DidValueChangeHandler = (String) -> Void +``` + +## Initializers + +### `init(value:keyboardType:)` + +``` swift +public init(value: String, keyboardType type: UIKeyboardType) +``` + +## Methods + +### `willInputUpdateHandler(_:)` + +``` swift +@discardableResult public func willInputUpdateHandler(_ willInputUpdateHandler: @escaping WillValueChangeHandler) -> Self +``` + +### `inputHandler(_:)` + +``` swift +@discardableResult public func inputHandler(_ inputHandler: @escaping DidValueChangeHandler) -> Self +``` + +### `textView(_:shouldChangeTextIn:replacementText:)` + +``` swift +public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool +``` + +### `textViewDidChange(_:)` + +``` swift +public func textViewDidChange(_ textView: UITextView) +``` diff --git a/documentation/NavButton.md b/documentation/NavButton.md new file mode 100644 index 0000000..d28852e --- /dev/null +++ b/documentation/NavButton.md @@ -0,0 +1,23 @@ +# NavButton + +``` swift +@available(iOS 9.0, *) public class NavButton: Button +``` + +## Inheritance + +[`Button`](/Button) + +## Initializers + +### `init(title:tapHandler:destination:style:titleColor:backgroundColor:)` + +``` swift +public init(title: String, tapHandler: (() -> Void)? = nil, destination: @escaping () -> UIViewController, style: Navigate.NavigationStyle, titleColor: UIColor? = nil, backgroundColor: UIColor? = nil) +``` + +### `init(tapHandler:destination:style:labelView:)` + +``` swift +public init(tapHandler: (() -> Void)? = nil, destination: @escaping () -> UIViewController, style: Navigate.NavigationStyle, labelView: () -> UIView) +``` diff --git a/documentation/Navigate.md b/documentation/Navigate.md new file mode 100644 index 0000000..c7905a2 --- /dev/null +++ b/documentation/Navigate.md @@ -0,0 +1,200 @@ +# Navigate + +``` swift +@available(iOS 9.0, *) public class Navigate +``` + +## Initializers + +### `init(controller:)` + +``` swift +public init(controller: UINavigationController? = nil) +``` + +## Properties + +### `shared` + +``` swift +var shared: Navigate +``` + +## Methods + +### `configure(controller:)` + +Configure the Navigate Singleton with the Root Navigation Controller + +``` swift +@discardableResult public func configure(controller: UINavigationController?) -> Self +``` + +### `set(title:)` + +Set the visibleViewController's title + +``` swift +@discardableResult public func set(title: String) -> Self +``` + +#### Parameters + + - title: The title of the currentViewController + +### `setLeft(barButton:animated:)` + +Set the left barButton + +``` swift +@discardableResult public func setLeft(barButton: UIBarButtonItem?, animated: Bool = true) -> Self +``` + +#### Parameters + + - barButton: The UIBarButtonItem to be set + - animated: Should animate setting the left UIBarButtonItem + +### `setRight(barButton:animated:)` + +Set the right barButton + +``` swift +@discardableResult public func setRight(barButton: UIBarButtonItem?, animated: Bool = true) -> Self +``` + +#### Parameters + + - barButton: The UIBarButtonItem to be set + - animated: Should animate setting the right UIBarButtonItem + +### `setLeft(barButtons:animated:)` + +Set the left barButtons + +``` swift +@discardableResult public func setLeft(barButtons: [UIBarButtonItem]?, animated: Bool = true) -> Self +``` + +#### Parameters + + - barButton: The \[UIBarButtonItem\] to be set + - animated: Should animate setting the left \[UIBarButtonItem\] + +### `setRight(barButtons:animated:)` + +Set the right barButtons + +``` swift +@discardableResult public func setRight(barButtons: [UIBarButtonItem]?, animated: Bool = true) -> Self +``` + +#### Parameters + + - barButton: The \[UIBarButtonItem\] to be set + - animated: Should animate setting the right \[UIBarButtonItem\] + +### `go(_:style:completion:)` + +Go to a viewController by using the configured NavigationController + +``` swift +public func go(_ viewController: UIViewController, style: NavigationStyle, completion: (() -> Void)? = nil) +``` + +#### Parameters + + - viewController: UIViewController to navigate to + - style: Style of navigation + +### `go(from:to:style:completion:)` + +Go to a viewController by using another viewController + +``` swift +public func go(from: UIViewController, to: UIViewController, style: NavigationStyle, completion: (() -> Void)? = nil) +``` + +#### Parameters + + - from: The UIViewController that is handling the navigation + - viewController: UIViewController to navigate to + - style: Style of navigation + +### `back(toRoot:)` + +Navigate back and dismiss the visibleViewController + +``` swift +public func back(toRoot: Bool = false) +``` + +#### Parameters + + - toRoot: Should navigate back to the rootViewController + +### `dismiss()` + +Dismiss the visibleViewController + +``` swift +public func dismiss() +``` + +### `alert(title:message:withActions:secondsToPersist:_:)` + +Show an Alert + +``` swift +public func alert(title: String, message: String, withActions actions: [UIAlertAction] = [], secondsToPersist: Double?, _ closure: ((UIAlertController) -> Void)? = nil) +``` + +#### Parameters + + - title: Title of the UIAlertController + - message: Message of the UIAlertController + - withactions: Array of action objects to be added to the Alert + - secondsToPersist: Amount of seconds the Alert should show before dismissing itself + - closure: A closure that is passed the UIAlertController before presenting it + +### `actionSheet(title:message:withActions:_:)` + +Show an ActionSheet + +``` swift +public func actionSheet(title: String, message: String, withActions actions: [UIAlertAction] = [], _ closure: ((UIAlertController) -> Void)? = nil) +``` + +#### Parameters + + - title: Title of the UIAlertController + - message: Message of the UIAlertController + - withactions: Array of action objects to be added to the ActionSheet + - closure: A closure that is passed the UIAlertController before presenting it + +### `toast(style:pinToTop:secondsToPersist:animationInDuration:animationOutDuration:padding:tapHandler:_:)` + +Show a Toast Message + +``` swift +@available(iOS 11.0, *) public func toast(style: ToastStyle = .custom, pinToTop: Bool = true, secondsToPersist: Double? = nil, animationInDuration: Double = 0.5, animationOutDuration: Double = 0.5, padding: Float = 8, tapHandler: @escaping (UIView) -> Void = { $0.removeFromSuperview() }, _ closure: @escaping () -> UIView) +``` + +#### Parameters + + - style: The ToastStyle (default: .custom) + - pinToTop: Should the Toast pin to the top or bottom (default: true) + - secondsToPersist: Amount of seconds the Toast should show before dismissing itself + - animationInDuration: The amount of seconds the Toast should fade in (default: 0.5) + - animationOutDuration: The amount of seconds the Toast should fade out (default: 0.5) + - padding: The amount of spacing around the Toast + - tapHandler: What happens when the user taps on the Toast (default: { $0.removeFromSuperview() }) + - closure: A trailing closure that accepts a view + +### `destroyToast()` + +Destory the toast + +``` swift +public func destroyToast() +``` diff --git a/documentation/Navigate_NavigationStyle.md b/documentation/Navigate_NavigationStyle.md new file mode 100644 index 0000000..67ae849 --- /dev/null +++ b/documentation/Navigate_NavigationStyle.md @@ -0,0 +1,19 @@ +# Navigate.NavigationStyle + +``` swift +public enum NavigationStyle +``` + +## Enumeration Cases + +### `push` + +``` swift +case push +``` + +### `modal` + +``` swift +case modal +``` diff --git a/documentation/Navigate_ToastStyle.md b/documentation/Navigate_ToastStyle.md new file mode 100644 index 0000000..a4226c1 --- /dev/null +++ b/documentation/Navigate_ToastStyle.md @@ -0,0 +1,51 @@ +# Navigate.ToastStyle + +``` swift +public enum ToastStyle +``` + +## Enumeration Cases + +### `error` + +``` swift +case error +``` + +### `warning` + +``` swift +case warning +``` + +### `success` + +``` swift +case success +``` + +### `info` + +``` swift +case info +``` + +### `debug` + +``` swift +case debug +``` + +### `custom` + +``` swift +case custom +``` + +## Properties + +### `color` + +``` swift +var color: UIColor +``` diff --git a/documentation/ObservedView.md b/documentation/ObservedView.md new file mode 100644 index 0000000..a5b3d60 --- /dev/null +++ b/documentation/ObservedView.md @@ -0,0 +1,25 @@ +# ObservedView + +``` swift +@available(iOS 9.0, *) public class ObservedView: UIView where View: UIView +``` + +## Inheritance + +`UIView` + +## Initializers + +### `init(view:initialValue:onChangeHandler:)` + +``` swift +public init(view: View, initialValue: Value?, onChangeHandler: @escaping (_ newValue: Value?, _ view: View) -> Void) +``` + +## Methods + +### `update(value:)` + +``` swift +@discardableResult public func update(value: Value) -> Variable +``` diff --git a/documentation/Padding.md b/documentation/Padding.md new file mode 100644 index 0000000..03934cd --- /dev/null +++ b/documentation/Padding.md @@ -0,0 +1,31 @@ +# Padding + +``` swift +public enum Padding +``` + +## Enumeration Cases + +### `leading` + +``` swift +case leading(: Float) +``` + +### `trailing` + +``` swift +case trailing(: Float) +``` + +### `top` + +``` swift +case top(: Float) +``` + +### `bottom` + +``` swift +case bottom(: Float) +``` diff --git a/documentation/SafeAreaView.md b/documentation/SafeAreaView.md new file mode 100644 index 0000000..8b06cb7 --- /dev/null +++ b/documentation/SafeAreaView.md @@ -0,0 +1,25 @@ +# SafeAreaView + +A View that respects the SafeArea + +``` swift +@available(iOS 11.0, *) public class SafeAreaView: UIView +``` + +## Inheritance + +`UIView` + +## Initializers + +### `init(_:)` + +Create a SafeAreaView + +``` swift +public init(_ closure: () -> UIView) +``` + +#### Parameters + + - closure: A trailing closure that accepts a view diff --git a/documentation/ScrollView.md b/documentation/ScrollView.md new file mode 100644 index 0000000..208e4d3 --- /dev/null +++ b/documentation/ScrollView.md @@ -0,0 +1,17 @@ +# ScrollView + +``` swift +@available(iOS 9.0, *) public class ScrollView: UIScrollView +``` + +## Inheritance + +`UIScrollView` + +## Initializers + +### `init(_:)` + +``` swift +public init(_ closure: (() -> UIView)? = nil) +``` diff --git a/documentation/Slider.md b/documentation/Slider.md new file mode 100644 index 0000000..2561a07 --- /dev/null +++ b/documentation/Slider.md @@ -0,0 +1,17 @@ +# Slider + +``` swift +@available(iOS 9.0, *) public class Slider: UISlider +``` + +## Inheritance + +`UISlider` + +## Initializers + +### `init(value:from:to:valueChangedHandler:)` + +``` swift +public init(value: Float, from: Float, to: Float, valueChangedHandler: ((Float) -> Void)? = nil) +``` diff --git a/documentation/Spacer.md b/documentation/Spacer.md new file mode 100644 index 0000000..541be8c --- /dev/null +++ b/documentation/Spacer.md @@ -0,0 +1,17 @@ +# Spacer + +``` swift +@available(iOS 9.0, *) public class Spacer: UIView +``` + +## Inheritance + +`UIView` + +## Initializers + +### `init(height:width:)` + +``` swift +public init(height: Float? = nil, width: Float? = nil) +``` diff --git a/documentation/StringAttributes.md b/documentation/StringAttributes.md new file mode 100644 index 0000000..ab51f9e --- /dev/null +++ b/documentation/StringAttributes.md @@ -0,0 +1,5 @@ +# StringAttributes + +``` swift +public typealias StringAttributes = [AttributedStringKey: Any] +``` diff --git a/documentation/Switch.md b/documentation/Switch.md new file mode 100644 index 0000000..17712c4 --- /dev/null +++ b/documentation/Switch.md @@ -0,0 +1,17 @@ +# Switch + +``` swift +@available(iOS 9.0, *) public class Switch: UISwitch +``` + +## Inheritance + +`UISwitch` + +## Initializers + +### `init(isOn:toggleChanged:)` + +``` swift +public init(isOn: Bool = false, toggleChanged: ((Bool) -> Void)? = nil) +``` diff --git a/documentation/TableDidSelectIndexPathHandler.md b/documentation/TableDidSelectIndexPathHandler.md new file mode 100644 index 0000000..a39326c --- /dev/null +++ b/documentation/TableDidSelectIndexPathHandler.md @@ -0,0 +1,5 @@ +# TableDidSelectIndexPathHandler + +``` swift +public typealias TableDidSelectIndexPathHandler = (IndexPath) -> Void +``` diff --git a/documentation/TableHeaderFooterViewHandler.md b/documentation/TableHeaderFooterViewHandler.md new file mode 100644 index 0000000..c20e428 --- /dev/null +++ b/documentation/TableHeaderFooterViewHandler.md @@ -0,0 +1,5 @@ +# TableHeaderFooterViewHandler + +``` swift +public typealias TableHeaderFooterViewHandler = (Int) -> UIView? +``` diff --git a/documentation/TableHighlightIndexPathHandler.md b/documentation/TableHighlightIndexPathHandler.md new file mode 100644 index 0000000..07e0fa6 --- /dev/null +++ b/documentation/TableHighlightIndexPathHandler.md @@ -0,0 +1,5 @@ +# TableHighlightIndexPathHandler + +``` swift +public typealias TableHighlightIndexPathHandler = (IndexPath) -> Bool +``` diff --git a/documentation/TableView.md b/documentation/TableView.md new file mode 100644 index 0000000..7c157b3 --- /dev/null +++ b/documentation/TableView.md @@ -0,0 +1,363 @@ +# TableView + +``` swift +@available(iOS 11.0, *) public class TableView: UITableView +``` + +## Inheritance + +`UITableView`, `UITableViewDataSource`, `UITableViewDelegate` + +## Initializers + +### `init(initalData:style:)` + +``` swift +public init(initalData: [[CellDisplayable]] = [[CellDisplayable]](), style: UITableView.Style = .plain) +``` + +## Properties + +### `data` + +``` swift +var data: [[CellDisplayable]] +``` + +## Methods + +### `update(shouldReloadData:_:)` + +``` swift +@discardableResult func update(shouldReloadData: Bool = false, _ closure: ([[CellDisplayable]]) -> [[CellDisplayable]]) -> Self +``` + +### `append(shouldReloadData:_:)` + +``` swift +@discardableResult func append(shouldReloadData: Bool = false, _ closure: () -> [[CellDisplayable]]) -> Self +``` + +### `numberOfSections(in:)` + +``` swift +public func numberOfSections(in tableView: UITableView) -> Int +``` + +### `tableView(_:numberOfRowsInSection:)` + +``` swift +public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int +``` + +### `tableView(_:indentationLevelForRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, indentationLevelForRowAt indexPath: IndexPath) -> Int +``` + +### `tableView(_:cellForRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell +``` + +### `tableView(_:heightForHeaderInSection:)` + +``` swift +public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat +``` + +### `tableView(_:heightForFooterInSection:)` + +``` swift +public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat +``` + +### `tableView(_:viewForHeaderInSection:)` + +``` swift +public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? +``` + +### `tableView(_:viewForFooterInSection:)` + +``` swift +public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? +``` + +### `tableView(_:canEditRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool +``` + +### `tableView(_:canMoveRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool +``` + +### `tableView(_:canFocusRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, canFocusRowAt indexPath: IndexPath) -> Bool +``` + +### `tableView(_:shouldHighlightRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool +``` + +### `tableView(_:shouldIndentWhileEditingRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool +``` + +### `tableView(_:shouldShowMenuForRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool +``` + +### `tableView(_:editingStyleForRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle +``` + +### `tableView(_:titleForDeleteConfirmationButtonForRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? +``` + +### `tableView(_:editActionsForRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? +``` + +### `tableView(_:commit:forRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) +``` + +### `tableView(_:didSelectRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) +``` + +### `tableView(_:didDeselectRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) +``` + +### `tableView(_:willBeginEditingRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, willBeginEditingRowAt indexPath: IndexPath) +``` + +### `tableView(_:didEndEditingRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, didEndEditingRowAt indexPath: IndexPath?) +``` + +### `tableView(_:didHighlightRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath) +``` + +### `tableView(_:didUnhighlightRowAt:)` + +``` swift +public func tableView(_ tableView: UITableView, didUnhighlightRowAt indexPath: IndexPath) +``` + +### `tableView(_:moveRowAt:to:)` + +``` swift +public func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) +``` + +### `tableView(_:leadingSwipeActionsConfigurationForRowAt:)` + +``` swift +@available(iOS 11.0, *) public func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? +``` + +### `tableView(_:trailingSwipeActionsConfigurationForRowAt:)` + +``` swift +@available(iOS 11.0, *) public func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? +``` + +### `set(dataSource:)` + +``` swift +@discardableResult func set(dataSource: UITableViewDataSource) -> Self +``` + +### `set(delegate:)` + +``` swift +@discardableResult func set(delegate: UITableViewDelegate) -> Self +``` + +### `register(cells:)` + +``` swift +@discardableResult func register(cells: [TableViewCell.Type]) -> Self +``` + +### `headerView(_:)` + +``` swift +@discardableResult func headerView(_ handler: @escaping TableHeaderFooterViewHandler) -> Self +``` + +### `footerView(_:)` + +``` swift +@discardableResult func footerView(_ handler: @escaping TableHeaderFooterViewHandler) -> Self +``` + +### `headerHeight(_:)` + +``` swift +@discardableResult func headerHeight(_ handler: @escaping (Int) -> CGFloat) -> Self +``` + +### `footerHeight(_:)` + +``` swift +@discardableResult func footerHeight(_ handler: @escaping (Int) -> CGFloat) -> Self +``` + +### `indentationLevelForRowAtIndexPath(_:)` + +``` swift +@discardableResult func indentationLevelForRowAtIndexPath(_ handler: @escaping (IndexPath) -> Int) -> Self +``` + +### `canEditRowAtIndexPath(_:)` + +``` swift +@discardableResult func canEditRowAtIndexPath(_ handler: @escaping (IndexPath) -> Bool) -> Self +``` + +### `canMoveRowAtIndexPath(_:)` + +``` swift +@discardableResult func canMoveRowAtIndexPath(_ handler: @escaping (IndexPath) -> Bool) -> Self +``` + +### `canFocusRowAtIndexPath(_:)` + +``` swift +@discardableResult func canFocusRowAtIndexPath(_ handler: @escaping (IndexPath) -> Bool) -> Self +``` + +### `shouldHighlightRow(_:)` + +``` swift +@discardableResult func shouldHighlightRow(_ handler: @escaping TableHighlightIndexPathHandler) -> Self +``` + +### `shouldIndentWhileEditingRowAtIndexPath(_:)` + +``` swift +@discardableResult func shouldIndentWhileEditingRowAtIndexPath(_ handler: @escaping (IndexPath) -> Bool) -> Self +``` + +### `shouldShowMenuForRowAtIndexPath(_:)` + +``` swift +@discardableResult func shouldShowMenuForRowAtIndexPath(_ handler: @escaping (IndexPath) -> Bool) -> Self +``` + +### `editingStyleForRowAtIndexPath(_:)` + +``` swift +@discardableResult func editingStyleForRowAtIndexPath(_ handler: @escaping (IndexPath) -> UITableViewCell.EditingStyle) -> Self +``` + +### `titleForDeleteConfirmationButtonForRowAtIndexPath(_:)` + +``` swift +@discardableResult func titleForDeleteConfirmationButtonForRowAtIndexPath(_ handler: @escaping (IndexPath) -> String) -> Self +``` + +### `editActionsForRowAtIndexPath(_:)` + +``` swift +@discardableResult func editActionsForRowAtIndexPath(_ handler: @escaping (IndexPath) -> [UITableViewRowAction]) -> Self +``` + +### `commitEditingStyleForRowAtIndexPath(_:)` + +``` swift +@discardableResult func commitEditingStyleForRowAtIndexPath(_ handler: @escaping (UITableViewCell.EditingStyle, IndexPath) -> Void) -> Self +``` + +### `didSelectRow(_:)` + +``` swift +@discardableResult func didSelectRow(_ handler: @escaping TableDidSelectIndexPathHandler) -> Self +``` + +### `didDeselectRowAtIndexPath(_:)` + +``` swift +@discardableResult func didDeselectRowAtIndexPath(_ handler: @escaping (IndexPath) -> Void) -> Self +``` + +### `willBeginEditingRowAtIndexPath(_:)` + +``` swift +@discardableResult func willBeginEditingRowAtIndexPath(_ handler: @escaping (IndexPath) -> Void) -> Self +``` + +### `didEndEditingRowAtIndexPath(_:)` + +``` swift +@discardableResult func didEndEditingRowAtIndexPath(_ handler: @escaping (IndexPath?) -> Void) -> Self +``` + +### `didHighlightRowAtIndexPath(_:)` + +``` swift +@discardableResult func didHighlightRowAtIndexPath(_ handler: @escaping (IndexPath) -> Void) -> Self +``` + +### `didUnhighlightRowAtIndexPath(_:)` + +``` swift +@discardableResult func didUnhighlightRowAtIndexPath(_ handler: @escaping (IndexPath) -> Void) -> Self +``` + +### `moveRowAtSourceIndexPathToDestinationIndexPath(_:)` + +``` swift +@discardableResult func moveRowAtSourceIndexPathToDestinationIndexPath(_ handler: @escaping (IndexPath, IndexPath) -> Void) -> Self +``` + +### `leadingSwipeActionsConfigurationForRowAtIndexPath(_:)` + +``` swift +@discardableResult func leadingSwipeActionsConfigurationForRowAtIndexPath(_ handler: @escaping (IndexPath) -> UISwipeActionsConfiguration) -> Self +``` + +### `trailingSwipeActionsConfigurationForRowAtIndexPath(_:)` + +``` swift +@discardableResult func trailingSwipeActionsConfigurationForRowAtIndexPath(_ handler: @escaping (IndexPath) -> UISwipeActionsConfiguration) -> Self +``` diff --git a/documentation/TableViewCell.md b/documentation/TableViewCell.md new file mode 100644 index 0000000..9b03ccb --- /dev/null +++ b/documentation/TableViewCell.md @@ -0,0 +1,5 @@ +# TableViewCell + +``` swift +@available(iOS 11.0, *) public typealias TableViewCell = DataIdentifiable & CellConfigurable & CellUpdatable & UITableViewCell +``` diff --git a/documentation/TextField.md b/documentation/TextField.md new file mode 100644 index 0000000..500877a --- /dev/null +++ b/documentation/TextField.md @@ -0,0 +1,51 @@ +# TextField + +``` swift +@available(iOS 9.0, *) public class TextField: UITextField +``` + +## Inheritance + +`UITextField`, `UITextFieldDelegate` + +## Nested Type Aliases + +### `WillValueChangeHandler` + +``` swift +public typealias WillValueChangeHandler = (_ sender: UITextField, _ newValue: String, _ input: String) -> Bool +``` + +### `DidValueChangeHandler` + +``` swift +public typealias DidValueChangeHandler = (String) -> Void +``` + +## Initializers + +### `init(value:placeholder:keyboardType:)` + +``` swift +public init(value: String, placeholder: String, keyboardType type: UIKeyboardType) +``` + +## Methods + +### `willInputUpdateHandler(_:)` + +``` swift +@discardableResult public func willInputUpdateHandler(_ willInputUpdateHandler: @escaping WillValueChangeHandler) -> Self +``` + +### `inputHandler(_:)` + +``` swift +@discardableResult public func inputHandler(_ inputHandler: @escaping DidValueChangeHandler) -> Self +``` + +### `textField(_:shouldChangeCharactersIn:replacementString:)` + +``` swift +public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool +``` diff --git a/documentation/VScroll.md b/documentation/VScroll.md new file mode 100644 index 0000000..b97be2b --- /dev/null +++ b/documentation/VScroll.md @@ -0,0 +1,17 @@ +# VScroll + +``` swift +@available(iOS 9.0, *) public class VScroll: UIView +``` + +## Inheritance + +`UIView` + +## Initializers + +### `init(withPadding:_:)` + +``` swift +public init(withPadding padding: Float = 0, _ closure: () -> UIView) +``` diff --git a/documentation/VStack.md b/documentation/VStack.md new file mode 100644 index 0000000..08096f4 --- /dev/null +++ b/documentation/VStack.md @@ -0,0 +1,53 @@ +# VStack + +Vertical StackView + +``` swift +@available(iOS 9.0, *) public class VStack: UIView +``` + +## Inheritance + +`UIView` + +## Initializers + +### `init(withSpacing:padding:alignment:distribution:_:)` + +Create a VStack + +``` swift +public init(withSpacing spacing: Float = 0, padding: Float = 0, alignment: UIStackView.Alignment = .fill, distribution: UIStackView.Distribution = .fill, _ closure: () -> [UIView]) +``` + +#### Parameters + + - withSpacing: The amount of spacing between each child view + - padding: The amount of space between this view and its parent view + - alignment: The layout of arranged views perpendicular to the stack view’s axis (source: UIStackView.Alignment) + - distribution: The layout that defines the size and position of the arranged views along the stack view’s axis (source: UIStackView.Distribution) + - closure: A trailing closure that accepts an array of views + +### `init(withSpacing:padding:alignment:distribution:_:)` + +Create a VStack that accepts an array of UIView? + +``` swift +public init(withSpacing spacing: Float = 0, padding: Float = 0, alignment: UIStackView.Alignment = .fill, distribution: UIStackView.Distribution = .fill, _ closure: () -> [UIView?]) +``` + +#### Parameters + + - withSpacing: The amount of spacing between each child view + - padding: The amount of space between this view and its parent view + - alignment: The layout of arranged views perpendicular to the stack view’s axis (source: UIStackView.Alignment) + - distribution: The layout that defines the size and position of the arranged views along the stack view’s axis (source: UIStackView.Distribution) + - closure: A trailing closure that accepts an array of optional views + +## Methods + +### `update(views:)` + +``` swift +@discardableResult public func update(views closure: (inout [UIView]) -> Void) -> Self +``` diff --git a/documentation/VibrancyView.md b/documentation/VibrancyView.md new file mode 100644 index 0000000..0fee2b6 --- /dev/null +++ b/documentation/VibrancyView.md @@ -0,0 +1,17 @@ +# VibrancyView + +``` swift +@available(iOS 13.0, *) public class VibrancyView: UIVisualEffectView +``` + +## Inheritance + +`UIVisualEffectView` + +## Initializers + +### `init(blurStyle:vibrancyStyle:closure:)` + +``` swift +public init(blurStyle blur: UIBlurEffect.Style = UIBlurEffect.Style.regular, vibrancyStyle vibrancy: UIVibrancyEffectStyle = .fill, closure: () -> UIView) +``` diff --git a/documentation/ViewController.md b/documentation/ViewController.md new file mode 100644 index 0000000..3675031 --- /dev/null +++ b/documentation/ViewController.md @@ -0,0 +1,25 @@ +# ViewController + +``` swift +@available(iOS 9.0, *) public class ViewController: UIViewController +``` + +## Inheritance + +`UIViewController` + +## Initializers + +### `init(_:)` + +``` swift +public init(_ closure: @escaping (() -> UIView)) +``` + +## Methods + +### `viewDidLoad()` + +``` swift +public override func viewDidLoad() +``` diff --git a/documentation/WebView.md b/documentation/WebView.md new file mode 100644 index 0000000..dd3bd01 --- /dev/null +++ b/documentation/WebView.md @@ -0,0 +1,91 @@ +# WebView + +``` swift +@available(iOS 9.0, *) public class WebView: WKWebView +``` + +## Inheritance + +`WKWebView` + +## Initializers + +### `init()` + +``` swift +public init() +``` + +### `init(baseURL:htmlString:)` + +``` swift +convenience init(baseURL: URL? = nil, htmlString: () -> String) +``` + +### `init(url:)` + +``` swift +convenience init(url: URL) +``` + +### `init(request:)` + +``` swift +convenience init(request: URLRequest) +``` + +### `init(URL:allowingReadAccessTo:)` + +``` swift +convenience init(URL: URL, allowingReadAccessTo readAccessURL: URL) +``` + +### `init(data:mimeType:characterEncodingName:baseURL:)` + +``` swift +convenience init(data: Data, mimeType MIMEType: String, characterEncodingName: String, baseURL: URL) +``` + +## Methods + +### `loadHTMLString(baseURL:htmlString:)` + +``` swift +@discardableResult func loadHTMLString(baseURL: URL? = nil, htmlString: () -> String) -> Self +``` + +### `load(url:)` + +``` swift +@discardableResult func load(url: URL) -> Self +``` + +### `load(request:)` + +``` swift +@discardableResult func load(request: URLRequest) -> Self +``` + +### `loadFile(URL:allowingReadAccessTo:)` + +``` swift +@discardableResult func loadFile(URL: URL, allowingReadAccessTo readAccessURL: URL) -> Self +``` + +### `load(data:mimeType:characterEncodingName:baseURL:)` + +``` swift +@discardableResult func load(data: Data, mimeType MIMEType: String, characterEncodingName: String, baseURL: URL) -> Self +``` + +### `set(uiDelegate:)` + +``` swift +@discardableResult func set(uiDelegate delegate: WKUIDelegate) -> Self +``` + +### `set(navigationDelegate:)` + +``` swift +@discardableResult func set(navigationDelegate delegate: WKNavigationDelegate) -> Self +``` diff --git a/documentation/ZStack.md b/documentation/ZStack.md new file mode 100644 index 0000000..7be2573 --- /dev/null +++ b/documentation/ZStack.md @@ -0,0 +1,48 @@ +# ZStack + +ZStack:​ +A view which stacks its children views in order + +``` swift +@available(iOS 9.0, *) public class ZStack: UIView +``` + +## Inheritance + +`UIView` + +## Initializers + +### `init(_:)` + +Create a ZStack + +``` swift +public init(_ closure: () -> [UIView]) +``` + +#### Parameters + + - closure: A trailing closure that accepts an array of views + +### `init(_:)` + +Create a ZStack + +``` swift +public init(_ closure: () -> [UIView?]) +``` + +#### Parameters + + - closure: A trailing closure that accepts an array of optional views + +## Properties + +### `views` + +The views that the ZStack contains + +``` swift +var views: [UIView] = [] +``` diff --git a/documentation/_Footer.md b/documentation/_Footer.md new file mode 100644 index 0000000..04c3e07 --- /dev/null +++ b/documentation/_Footer.md @@ -0,0 +1 @@ +Generated at 2021-03-16T21:29:45-0500 using [swift-doc](https://github.com/SwiftDocOrg/swift-doc) 1.0.0-beta.5. diff --git a/documentation/_Sidebar.md b/documentation/_Sidebar.md new file mode 100644 index 0000000..1fcb9ba --- /dev/null +++ b/documentation/_Sidebar.md @@ -0,0 +1,65 @@ +
+Types + + - [BlurView](/BlurView) + - [Button](/Button) + - [CollectionView](/CollectionView) + - [ContainerView](/ContainerView) + - [Divider](/Divider) + - [EffectView](/EffectView) + - [HScroll](/HScroll) + - [HStack](/HStack) + - [Image](/Image) + - [Label](/Label) + - [List](/List) + - [LoadingImage](/LoadingImage) + - [LoadingView](/LoadingView) + - [Map](/Map) + - [MapPoint](/MapPoint) + - [MultiLineField](/MultiLineField) + - [NavButton](/NavButton) + - [Navigate](/Navigate) + - [Navigate.NavigationStyle](/Navigate.NavigationStyle) + - [Navigate.ToastStyle](/Navigate.ToastStyle) + - [ObservedView](/ObservedView) + - [Padding](/Padding) + - [SafeAreaView](/SafeAreaView) + - [ScrollView](/ScrollView) + - [Slider](/Slider) + - [Spacer](/Spacer) + - [Switch](/Switch) + - [TableView](/TableView) + - [TextField](/TextField) + - [VScroll](/VScroll) + - [VStack](/VStack) + - [VibrancyView](/VibrancyView) + - [ViewController](/ViewController) + - [WebView](/WebView) + - [ZStack](/ZStack) + +
+ +
+Protocols + + - [CellConfigurable](/CellConfigurable) + - [CellDisplayable](/CellDisplayable) + - [CellUpdatable](/CellUpdatable) + - [DataIdentifiable](/DataIdentifiable) + +
+ +
+Global Typealiases + + - [AttributedString](/AttributedString) + - [AttributedStringKey](/AttributedStringKey) + - [BarButton](/BarButton) + - [CollectionViewCell](/CollectionViewCell) + - [StringAttributes](/StringAttributes) + - [TableDidSelectIndexPathHandler](/TableDidSelectIndexPathHandler) + - [TableHeaderFooterViewHandler](/TableHeaderFooterViewHandler) + - [TableHighlightIndexPathHandler](/TableHighlightIndexPathHandler) + - [TableViewCell](/TableViewCell) + +