涡轮增压器

Turbocharger 旨在通过提供常用的视图和视图修饰符来加速 SwiftUI 开发。亮点包括用于更好支持动态类型的 AdaptiveStack 和用于关系布局的 WeightedVStack/WeightedHStack

使用 Engine 构建,兼顾性能和向后兼容性

另请参阅

系统要求

安装

Xcode 项目

选择 File -> Swift Packages -> Add Package Dependency 并输入 https://github.com/nathantannar4/Turbocharger

Swift Package Manager 项目

您可以在您的 Package.swift 文件中添加 Turbocharger 作为包依赖项

let package = Package(
    //...
    dependencies: [
        .package(url: "https://github.com/nathantannar4/Turbocharger"),
    ],
    targets: [
        .target(
            name: "YourPackageTarget",
            dependencies: [
                .product(name: "Turbocharger", package: "Turbocharger"),
            ],
            //...
        ),
        //...
    ],
    //...
)

Turbocharger 简介

启动 Turbocharger 有两个目标。1) 扩展 SwiftUI 提供的标准 API,使其包含许多人通常期望或需要的功能;以及 2) 演示如何使用 Engine 来创建可向后兼容的可重用组件。

LabeledView

/// The ``ViewStyle`` for ``LabeledView``
public protocol LabeledViewStyle: ViewStyle where Configuration == LabeledViewStyleConfiguration {
    associatedtype Configuration = Configuration
}

/// The ``ViewStyledView.Configuration`` for ``LabeledView``
public struct LabeledViewStyleConfiguration {
    /// A type-erased label of a ``LabeledView``
    public struct Label: ViewAlias { }
    public var label: Label

    /// A type-erased content of a ``LabeledView``
    public struct Content: ViewAlias { }
    public var content: Content
}

/// A backwards compatible port of `LabeledContent`
public struct LabeledView<Label: View, Content: View>: View {

    public init(
        @ViewBuilder content: () -> Content,
        @ViewBuilder label: () -> Label
    )
}

HVStack/AdaptiveStack

/// A view that arranges its subviews in a vertical or horizontal line.
@frozen
public struct HVStack<Content: View>: View {

    public init(
        axis: Axis,
        alignment: Alignment = .center,
        spacing: CGFloat? = nil,
        @ViewBuilder content: () -> Content
    )
}
    
/// A view that arranges its subviews in a horizontal line when such a layout
/// would fit the available space. If there is not enough space, it arranges it's subviews
/// in a vertical line.
@frozen
public struct AdaptiveStack<Content: View>: View {

    public init(
        alignment: Alignment = .center,
        spacing: CGFloat? = nil,
        @ViewBuilder content: () -> Content
    )
}

WeightedHStack/WeightedVStack

/// A view that arranges its subviews in a horizontal line a width
/// that is relative to its `LayoutWeightPriority`.
///
/// By default, all subviews will be arranged with equal width.
///
@frozen
public struct WeightedHStack<Content: View>: View {

    public init(
        alignment: VerticalAlignment = .center,
        spacing: CGFloat? = nil,
        @ViewBuilder content: () -> Content
    )
}

/// A view that arranges its subviews in a vertical line a height
/// that is relative to its `LayoutWeightPriority`.
///
/// By default, all subviews will be arranged with equal height.
///
@frozen
public struct WeightedVStack<Content: View>: View {

    public init(
        alignment: HorizontalAlignment = .center,
        spacing: CGFloat? = nil,
        @ViewBuilder content: () -> Content
    )
}

extension View {
    @ViewBuilder
    public func layoutWeight(_ value: Double) -> some View
}

FlowStack

/// A view that arranges its subviews along multiple horizontal lines.
@frozen
public struct FlowStack<Content: View>: View {

    public init(
        alignment: Alignment = .center,
        spacing: CGFloat? = nil,
        @ViewBuilder content: () -> Content
    )
}

RadialStack

/// A view that arranges its subviews along a radial circumference.
@frozen
public struct RadialStack<Content: View>: View {

    public init(radius: CGFloat? = nil, @ViewBuilder content: () -> Content)
}

OptionalAdapter

/// A view maps an `Optional` value to it's `Content` or `Placeholder`.
@frozen
public struct OptionalAdapter<
    T,
    Content: View,
    Placeholder: View
>: View {

    @inlinable
    public init(
        _ value: T?,
        @ViewBuilder content: (T) -> Content,
        @ViewBuilder placeholder: () -> Placeholder
    )
    
    @inlinable
    public init(
        _ value: Binding<T?>,
        @ViewBuilder content: (Binding<T>) -> Content,
        @ViewBuilder placeholder: () -> Placeholder
    )
}

extension OptionalAdapter where Placeholder == EmptyView {
    @inlinable
    public init(
        _ value: T?,
        @ViewBuilder content: (T) -> Content
    )
    
    @inlinable
    public init(
        _ value: Binding<T?>,
        @ViewBuilder content: (Binding<T>) -> Content
    )
}

ResultAdapter

/// A view maps a `Result` value to it's `SuccessContent` or `FailureContent`.
@frozen
public struct ResultAdapter<
    SuccessContent: View,
    FailureContent: View
>: View {

    @inlinable
    public init<Success, Failure: Error>(
        _ value: Result<Success, Failure>,
        @ViewBuilder content: (Success) -> SuccessContent,
        @ViewBuilder placeholder: (Failure) -> FailureContent
    )
    
    @inlinable
    public init<Success, Failure: Error>(
        _ value: Binding<Result<Success, Failure>>,
        @ViewBuilder content: (Binding<Success>) -> SuccessContent,
        @ViewBuilder placeholder: (Binding<Failure>) -> FailureContent
    )
}

extension ResultAdapter where FailureContent == EmptyView {
    @inlinable
    public init<Success, Failure: Error>(
        _ value: Result<Success, Failure>,
        @ViewBuilder content: (Success) -> SuccessContent
    )
    
    @inlinable
    public init<Success, Failure: Error>(
        _ value: Binding<Result<Success, Failure>>,
        @ViewBuilder content: (Binding<Success>) -> SuccessContent
    )
}

BindingTransform

public protocol BindingTransform {
    associatedtype Input
    associatedtype Output

    func get(_ value: Input) -> Output
    func set(_ newValue: Output, oldValue: @autoclosure () -> Input) throws -> Input
}

extension Binding {
@inlinable
    public func projecting<Transform: BindingTransform>(
        _ transform: Transform
    ) -> Binding<Transform.Output> where Transform.Input == Value

    @inlinable
    public func isNil<Wrapped>() -> Binding<Bool> where Optional<Wrapped> == Value
    
    @inlinable
    public func isNotNil<Wrapped>() -> Binding<Bool> where Optional<Wrapped> == Value
    
    @inlinable
    public func map<T>(_ keyPath: WritableKeyPath<Value, T>) -> Binding<T>
}

SafeAreaPadding

@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
extension View {
    @inlinable
    public func safeAreaPadding(_ edgeInsets: EdgeInsets) -> some View

    @inlinable
    public func safeAreaPadding(_ length: CGFloat = 16) -> some View

    @inlinable
    public func safeAreaPadding(_ edges: Edge.Set, _ length: CGFloat = 16) -> some View
}

Badge

@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
extension View {
    @inlinable
    public func badge<Label: View>(
        alignment: Alignment = .topTrailing,
        anchor: UnitPoint = UnitPoint(x: 0.25, y: 0.25),
        scale:  CGFloat = 1.2,
        @ViewBuilder label: () -> Label
    ) -> some View
}

辅助功能

extension View {
    /// Disables accessibility elements from being generated, even when an assistive technology is running
    @inlinable
    public func accessibilityDisabled() -> some View

    /// Optionally uses the specified string to identify the view.
    @inlinable
    public func accessibilityIdentifier(_ identifier: String?) -> ModifiedContent<Self, AccessibilityAttachmentModifier>

    /// Optionally adds a label to the view that describes its contents.
    @_disfavoredOverload
    @inlinable
    public func accessibilityLabel<S: StringProtocol>(_ label: S?) -> ModifiedContent<Self, AccessibilityAttachmentModifier>

    /// Optionally adds a textual description of the value that the view contains.
    @_disfavoredOverload
    @inlinable
    public func accessibilityValue<S: StringProtocol>(_ value: S?) -> ModifiedContent<Self, AccessibilityAttachmentModifier>
    
    /// Optionally adds an accessibility action to the view.
    @inlinable
    public func accessibilityAction(named name: LocalizedStringKey?, _ handler: @escaping () -> Void) -> ModifiedContent<Self, AccessibilityAttachmentModifier>

    /// Optionally adds an accessibility action to the view.
    @_disfavoredOverload
    @inlinable
    public func accessibilityAction<S: StringProtocol>(named name: S?, _ handler: @escaping () -> Void) -> ModifiedContent<Self, AccessibilityAttachmentModifier>

以及更多

请查看源文件了解更多信息。

许可证

根据 BSD 2-Clause 许可证分发。有关更多信息,请参阅 LICENSE.md