已弃用

该库已被弃用,建议使用枚举和 swiftui-navigation 正确地对导航域进行建模。

MultiModal

CI

简介

默认情况下,在同一个 body 中具有多个模态修饰符(例如,.sheet.alert)的 SwiftUI 视图只会使用修饰符链中的最后一个,并忽略之前的所有修饰符。

struct NoMultiModalDemoView: View {
    @State var sheetAPresented = false
    @State var sheetBPresented = false
    @State var sheetCPresented = false

    var body: some View {
        VStack(spacing: 20) {
            Button("Sheet A") { sheetAPresented = true }
            Button("Sheet B") { sheetBPresented = true }
            Button("Sheet C") { sheetCPresented = true }
        }
        .sheet(isPresented: $sheetAPresented) { Text("Sheet A") } // does not work
        .sheet(isPresented: $sheetBPresented) { Text("Sheet B") } // does not work
        .sheet(isPresented: $sheetCPresented) { Text("Sheet C") } // works
    }
}

MultiModal 引入了一个 .multiModal 修饰符,可以在同一个视图 body 中声明多个模态修饰符。

struct MultiModalDemoView: View {
    @State var sheetAPresented = false
    @State var sheetBPresented = false
    @State var sheetCPresented = false

    var body: some View {
        VStack(spacing: 20) {
            Button("Sheet A") { sheetAPresented = true }
            Button("Sheet B") { sheetBPresented = true }
            Button("Sheet C") { sheetCPresented = true }
        }
        .multiModal {
            $0.sheet(isPresented: $sheetAPresented) { Text("Sheet A") } // works
            $0.sheet(isPresented: $sheetBPresented) { Text("Sheet B") } // works
            $0.sheet(isPresented: $sheetCPresented) { Text("Sheet C") } // works
        }
    }
}

免责声明

MultiModal 不支持“嵌套”模态;它只是允许在视图 body 中一次显示多个模态。 因此,建议您的模态呈现依赖于一个真值来源,以确保在任何给定时间只呈现其中一个。

希望 Apple 在 SwiftUI 的未来版本中引入对多个模态的支持,从而使该库变得不必要。

基准测试

MacBook Pro (14-inch, 2021)
Apple M1 Pro (10 cores, 8 performance and 2 efficiency)
32 GB Memory

$ swift run -c release Benchmarks

name     time        std        iterations
------------------------------------------
Modifier 2416.000 ns ±  15.72 %     571301