Alert、Menu

  • Alert
  • Alert内创立TextFiele
  • Alert-Button增加action
  • 怎么在一个视图中显现多个alert
  • 怎么显现Alert的Sheet
  • 创立Menu
  • 运用appStoreOverlay()引荐另一个运用
  • Menu的显现方式
  • Picker的Menu

概述

文章首要分享SwiftUI Modifier的学习过程,将运用事例的方式进行阐明。内容浅显易懂,Alert展现部分调试成果,不过测验代码是完全的。假如想要运行成果,能够移步Github下载code -> github事例链接

1、Alert

SwiftUI能够经过alert()修饰符向用户显现弹出框,取决于是针对iOS15或更高的版别,仍是需求支撑iOS13和14。API有一些差异。在iOS15,要显现alert,先创立一些bool状态来确定alert是否应该可见,然后将其与期望在alert中显现的一切按钮一起附加到alert()修饰符。一切按钮在点击时都会封闭alert,因而能够理解为封闭是一个空操作。

1.1、根底Alert

创立一个带有“OK”的alert

struct FFAlertShow: View {
    @State private var showingAlert = false
    var body: some View {
        Button("Show alert") {
            showingAlert = true
        }
        .alert("Important message", isPresented: $showingAlert) {
            Button("OK", role: .cancel) { }
        } 
    }
}

像这样显现alert会在点击按钮时主动将showingAlert设置为false。能够依据需求创立尽或许多的按钮,假如没有创立按钮,那么会主动得到一个默许的“OK”来封闭alert。由于这些都是SwiftUI按钮,能够分配其他的role,比如,.destructive来让体系对他们进行恰当的款式化。

1.2、多个Button的Alert

创立带有多个Button的alert,要显现alert,榜首种方法是界说某种可绑定条件。以确定alert是否应该可见。然后将其附加到主视图上,一旦其条件为真,主视图就会显现alert。

struct FFAlertShow: View {
    @State private var showingAlert2 = false
    var body: some View {
        Button("Show Alert For Buttons") {
            showingAlert2 = true
        }
        .alert("Important message", isPresented: $showingAlert2) {
            Button("First", role: .destructive) { }
            Button("Second", role: .destructive) { }
            Button("Third", role: .destructive) { }
            Button("Cancel", role: .cancel) { }
        }
    }
}

1.3、带有message的Alert

例如,这段代码创立了一个showingAlert的bool值,它跟踪防晒信息是否应该被显现,当按钮被点击时将Bool值设置为true,然后运用该bool值创立并附加一个alert视图,一边在按钮被点击时运用。

struct FFAlertShow: View {
    @State private var showingAlert3 = false
    var body: some View {
        Button("Show Alert") {
            showingAlert3 = true
        }
        .alert(isPresented: $showingAlert3) {
            Alert(title: Text("metabblv"), message: Text("Wear sunscreen"), dismissButton: .default(Text("Got it!")))
        }
    }
}

1.4、经过Identifiable可选状态创立Alert

创立Alert的第二种方法是绑定到一些符号Identifiable的可选状态,这将导致在目标的值发生变化时弹出alert。这种方法有两个有优点:

  • 能够在运行时附加任何目标,因而alert能够显现任意数量的不同数据块。
  • SwiftUI会在可选值有值的时分主动展开,这样就能够在想要显现alert的时分确定他的存在。不需求自己查看和展开。
struct TVShow: Identifiable {
    var id: String { name }
    let name: String
}
struct FFAlertShow: View {
    @State private var selectedShow: TVShow?
    var body: some View {
        //例如,这显现了一个alert,依据挑选的TV show you两个不同的值。
        Divider()
        VStack(spacing:20) {
            Text("What is your favorite TV Show?")
                .font(.largeTitle)
            Button("Select Ted Lasso") {
                selectedShow = TVShow(name: "Ted Lasso")
            }
            Button("Select Bridgerton") {
                selectedShow = TVShow(name: "Bridgerton")
            }
        }
        .alert(item: $selectedShow) { show in
            Alert(title: Text(show.name), message: Text("Great choice!"), dismissButton: .cancel())
        }
    }
}

调试成果

SwiftUI基础篇Alert
SwiftUI基础篇Alert
SwiftUI基础篇Alert
SwiftUI基础篇Alert
SwiftUI基础篇Alert

2、Alert内创立TextFiele

SwiftUI的alert能够创立一个或多个TextField或SecureField视图,提示用户直接输入。

2.1、根底款式

能够增加一个TextField,让用户在alert中输入自己的名字

struct FFAlertTextField: View {
    @State private var showingAlert = false
    @State private var name = ""
    var body: some View {
        Button("Enter name") {
            showingAlert.toggle()
        }
        .alert("Enter your name", isPresented: $showingAlert) {
            TextField("username", text: $name)
            Button("OK", action: submit)
        } message: {
            Text("Xcode will print whatever you type")
        }
    }
    func submit() {
        print("Your entered \(name)")
    }
}

2.2、混合TextField和SecureText

能够增加尽或许多的字段,混合TextField和SecureText依据需求。例如,这显现了一个登陆提示,要求用户在alert中输入用户名和密码。

struct FFAlertTextField: View {
    @State private var isAuthentication = false
    @State private var username = ""
    @State private var password = ""
    var body: some View {
        Button("Please enter you Authentication") {
            isAuthentication.toggle()
        }
        .alert("Login in", isPresented: $isAuthentication) {
            TextField("username", text: $username)
            SecureField("password", text: $password)
            Button("OK", action: authenticate)
            Button("Cancel", role: .cancel) { }
        } message: {
            Text("Please enter your user and Password")
        }
    }
    func authenticate() {
        if username == "metabblv" && password == "123456" {
            print("login successed")
        } else {
            print("login failed")
        }
    }
}

调试成果

SwiftUI基础篇Alert
SwiftUI基础篇Alert

3、Alert-Button增加action

常常需求将操作附加到Button上,以便在点击按钮时执行特定的操作,要做到这一点,给按钮附加一个闭包,当他被点击时将被调用。

struct FFAlertAddAction: View {
    @State private var shwoingAlert = false
    var body: some View {
        Button("Show Alert") {
            shwoingAlert = true
        }
        .alert(isPresented: $shwoingAlert) {
            Alert(title: Text("你确定要删去数据吗?"), message: Text("这是一个不可逆操作。"), primaryButton: .destructive(Text("删去"), action: {
                print("正在删去")
            }), secondaryButton: .cancel(Text("撤销")))
        }
    }
}

假如要增加两个以上的Button,运用Sheet。

调试成果

iPhone

SwiftUI基础篇Alert

terminal

applicationDidFinishLaunching
正在删去

4、怎么在一个视图中显现多个alert

SwiftUI使得显现单个alert相对容易,可是假如试图从一个视图中显现两个或更多的alert,就变得很困难,会呈现一个alert好用,另外一个不好用。要处理这个问题,需求保证为每个视图附加不超越一个alert修饰符。看起来或许有一些约束,只需记住一点,不需求将alert附加到同一个视图,能够将他们附加到任何地方。事实上,或许会发现将他们直接附加到显现他们的View上更准确。

能够编写一些代码来界说两个@State属性,每个属性操控显现的alert,不是将两个alert修饰符附加到同一个VStack上,而是将他们分别附加到担任显现该alert的按钮上。

struct FFAlertMultiple: View {
    @State private var showingAlert1 = false
    @State private var showingAlert2 = false
    var body: some View {
        VStack {
            Button("Show 1") {
                showingAlert1 = true
            }
            .alert(isPresented: $showingAlert1) {
                Alert(title: Text("One"), message: nil, dismissButton: .cancel())
            }
            Button("Show 2") {
                showingAlert2 = true
            }
            .alert(isPresented: $showingAlert2, content: {
                Alert(title: Text("Two"), message: nil, dismissButton: .cancel())
            })
        }
    }
}

假如测验将alert()修饰符都移动到VStack中,你就会发现只要一个有效。

5、怎么显现Alert的Sheet

SwiftUI能够运用confirmationDialog()修饰符向用户显现一个选项。要运用confirmationDialog()创立sheet,需求供给一些titleText、一个绑定来决议何时显现Action的sheet以及你是否想要标题文本,假如你没有指定,SwiftUI将依据上下文来为你决议。

5.1、根底款式

struct FFAlertSheet: View {
    @State private var showingOptions = false
    @State private var selection = "None"
    var body: some View {
        VStack {
            Text(selection)
            Button("Confirm paint color") {
                showingOptions = true
            }
            .confirmationDialog("Select a color", isPresented: $showingOptions, titleVisibility: .visible) {
                Button("Red") {
                    selection = "Red"
                }
                Button("Green") {
                    selection = "Green"
                }
                Button("Blue") {
                    selection = "Blue"
                }
            }
        }
    }
}

5.2、For循环创立

这个API对每个Action运用一个标准的SwiftUI按钮,所以能够附加一个role,比如.desturective,让SwiftUI给它恰当的上色。能够运用ForEach将这些动作分解成一个简略的循环。

struct FFAlertSheet: View {
    @State private var showingOptions2 = false
    @State private var selection2 = "None"
    var body: some View {
        VStack {
            Text(selection2)
            Button("Confirm paint color 2") {
                showingOptions2 = true
            }
            .confirmationDialog("Select a color", isPresented: $showingOptions2, titleVisibility: .visible) {
                ForEach(["Red", "Green", "Blue"], id: \.self) { color in
                    Button(color) {
                        selection2 = color
                    }
                }
            }
        }
    }
}

调试成果

SwiftUI基础篇Alert
SwiftUI基础篇Alert

6、创立Menu

SwiftUI供给了ContextMenu修饰符,用于在app中创立弹出式菜单。在iOS中,这通常是长按触发的,但它的作业原理与macOS上的右键相同。contextMenu是由按钮组成的,每个按钮都有自己的动作、文本和图标。文本和图标能够直接在按钮中设置。由于SwiftUI将供给一个隐式的HStack来保证他们符合体系标准的外观和感觉。

所以,假如我们想要一个上下文menu附加到一些文本上,能够为菜单供给两个按钮。

struct FFMenuContent: View {
    var body: some View {
        Text("Options")
            .contextMenu(ContextMenu(menuItems: {
                Button {
                    print("Change country setting")
                } label: {
                    Label("Choose Country", systemImage: "globe")
                }
                Button(action: {
                    print("Enable geolocation")
                }, label: {
                    Label("Detect Location", systemImage: "location.circle")
                })
            }))
    }
}

要在iOS上测验一下,长按“Options”文本弹出来的菜单,或者在macOS上右键。此修饰符能够附加到任何SwiftUI视图。

调试成果

长按

SwiftUI基础篇Alert

7、运用appStoreOverlay()引荐另一个运用

SwiftUI给了一个专门的修改器,能够引荐AppStore上的其他运用,这是一个很好的穿插引荐的方式。假如你运用的是App Clips,这一点尤其有用,一旦用户完成了首要操作,你就能够从App Clips中引荐完好的运用。这个修饰符需求一些状态来观察,这将决议App Store掩盖是否激活,以及SDKOverlay。确定要引荐哪个运用程序AppConfiguration。 appStoreOverlay在macOS上不可用。

例如,当按钮被按下时,它会引荐一个特定的App

struct FFAppStroeOverlay: View {
    @State private var showRecommended = false
    var body: some View {
        Button("Show Recommended App") {
            showRecommended.toggle()
        }
        .appStoreOverlay(isPresented: $showRecommended) {
            SKOverlay.AppConfiguration(appIdentifier: "1440611372", position: .bottom)
        }
    }
}

需求导入StoreKit结构来运用SKOverlay。

调试成果

SwiftUI基础篇Alert
SwiftUI基础篇Alert

8、Menu的显现

SwiftUI供给了一个专门的视图来显现按钮弹出时菜单。这能够经过简略的字符串或运用自界说视图创立,但不管哪种方式,都能够运用各种按钮来操控想要的菜单中显现的内容。在macOS上,菜单会主动呈现下拉按钮。

8.1、根底款式

struct FFMenuShow: View {
    var body: some View {
        Menu("Options") {
            Button("Order Now") {
                print("Order Now")
            }
            Button("Adjust Order") {
                print("Adjust Order")
            }
            Button("Cancel") {
                print("Cancel")
            }
        }
    }
}

8.2、嵌套menu

也能够在菜单中放置菜单,这将导致iOS在点击榜首个选项的时分弹出第二个菜单

struct FFMenuShow: View {
    var body: some View {
        Menu("Options") {
            Button("Order Now") {
                print("Order Now")
            }
            Menu("Advanced") {
                Button("Rename") {
                    print("Rename")
                }
                Button("Delay") {
                    print("Delay")
                }
            }
            Button("Adjust Order") {
                print("Adjust Order")
            }
            Button("Cancel") {
                print("Cancel")
            }
        }
        //假如你想运用一些文本和图标自界说Label
        Menu {
            Button("Order Now") {
                print("Order Now")
            }
            Button("Adjust Order") {
                print("Adjust Order")
            }
        } label: {
            Label("Options", systemImage: "paperplane")
        }
    }
}

8.3、丰富款式

假如想运用一些文本和图标自界说Label

struct FFMenuShow: View {
    var body: some View {
        Menu {
            Button("Order Now") {
                print("Order Now")
            }
            Button("Adjust Order") {
                print("Adjust Order")
            }
        } label: {
            Label("Options", systemImage: "paperplane")
        }
    }
}

调试成果

SwiftUI基础篇Alert
SwiftUI基础篇Alert
SwiftUI基础篇Alert

9、Picker的Menu

SwiftUI的Picker视图有一个名为.menu的专用款式,它显现了一个弹出式菜单的选项,挑选器的标签显现为一个可点击的按钮。菜单自身将在当前挑选的选项周围主动显现一个复选标记,并能够依据挑选器在屏幕上的位置向上或向下显现。

struct FFMenuPick: View {
    @State private var selection = "Red"
    let colors = ["Red", "Green", "Blue", "Black", "Tartan"]
    var body: some View {
        VStack {
            Picker("Select a paint color", selection: $selection) {
                ForEach(colors, id: \.self) {
                    Text($0)
                }
            }
            .pickerStyle(.menu)
            Text("Selected color: \(selection)")
        }
    }
}

调试成果

SwiftUI基础篇Alert
SwiftUI基础篇Alert