ComposableFullscreenPopup

一个针对 Composable Architecture 优化的库,能够轻松地在导航栏上方呈现可定制的弹窗。

动机

ComposableFullscreenPopup 是 FullscreenPopup 库的扩展,专门为 SwiftUI 设计并针对 Composable Architecture 进行了优化。该库解决了在 SwiftUI 中显示自定义警告框的挑战,尤其是在涉及模态视图的情况下。诸如使用 ZStack 或 overlay 修饰符之类的标准方法受到限制,因为它们被限制在活动模态视图的范围内,从而阻止了对捕获用户全部注意力的全屏扩展至关重要。

我们的解决方案利用了 fullscreenCover 修饰符,允许自定义警告框在整个屏幕上显示,而与任何活动模态视图无关。这确保了自定义警告框不受模态边界的限制,从而使它们能够完全覆盖背景内容并防止意外交互。

ZStack 或 overlay 本库

用法

以下是使用方法

import SwiftUI
import ComposableArchitecture
import ComposableFullscreenPopup

@Reducer
public struct MyReducer: Reducer {
    public struct State: Equatable {
        @PresentationState var popup: PopupReducer.State?
        public init() {}
    }

    public enum Action {
        case popup(PresentationAction<PopupReducer.Action>)
    }

    public var body: some ReducerOf<Self> {
        Reduce { state, action in
            ...
        }
        .ifLet(\.$popup, action: \.popup) {
            PopupReducer()
        }
    }
}

public struct MyView: View {
    let store: StoreOf<MyReducer>
    ...
    public var body: some View {
        ...
        .popup(store.scope(state: \.$popup, action: { .popup($0) })) { store in
            PopupView(store: store)
        }
    }
}

自定义动画

您还可以通过向 .popup 修饰符提供 animation 参数来自定义动画。这是一个例子

.popup(store.scope(state: \.$popup, action: { .popup($0) }), duration: .seconds(0.5), animation: .easeIn(duration: 0.5)) {
    // Your custom popup content
}

警告 duration 参数必须大于 animationduration

自定义背景

您还可以自定义出现在弹出窗口后面的背景视图。默认情况下,使用半透明的黑色视图。要使用不同的视图,请向 .popup 修饰符提供 background 参数

.popup(store.scope(state: \.$popup, action: { .popup($0) })) { isPresented in
    LinearGradient(gradient: Gradient(colors: [.blue, .purple]), startPoint: .top, endPoint: .bottom)
        .opacity(isPresented ? 0.5 : 0)
} content: {
    // Your custom popup content
}

安装

let package = Package(
    name: "YourProject",
    ...
    dependencies: [
        .package(url: "https://github.com/Ryu0118/swift-composable-fullscreen-popup", exact: "0.1.0")
    ],
    targets: [
        .target(
            name: "YourTarget",
            dependencies: [
                .product(name: "ComposableFullscreenPopup", package: "swift-composable-fullscreen-popup"),
            ]
        )
    ]
)