6

让不懂编程的人爱上iPhone开发( iOS13+Swift5.1+Xcode11版)-08

 3 years ago
source link: https://zhuanlan.zhihu.com/p/141232518
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

让不懂编程的人爱上iPhone开发( iOS13+Swift5.1+Xcode11版)-08

苹果粉丝,摄影迷,心理学爱好者

欢迎继续我们的学习。

在上一课的内容中,我们通过print()函数在Console视图中添加了一个只有开发者可以看到,用户完全没感觉的按钮交互,略有点坑。

接下来我们将学习如何让用户也可以跟我们的按钮交互。

State和SwiftUI

作为iOS开发的新概念,SwiftUI的核心之一就是state。

那么到底什么是state呢?我们先不要查英汉词典,先来看看很多人比较熟悉的东西,也就是汽车的仪表盘。

在汽车的仪表盘中,车速里程表、和燃油表等算是最重要的组成部分了,

通过这些仪表,我们可以轻松查看汽车的当前驾驶速度、燃油油位、引擎温度和驾驶历程等信息,每种信息都可以用一个数字来表示。

除此之外,仪表盘还提供了各种警示灯,比如“引擎检查”灯,低油量警示灯,安全带未正确佩戴警示灯,等等。以上各种警示灯要吗开启,以提示司机汽车可能存在某方面需要注意的问题,要吗处于关闭状态,表示一切安好(至少在电子仪器测量的眼中)。这些开关状态信息可以用binary二进制来表示。

以上的所有信息,包括仪表盘上显示的各种数字信息,以及警示灯的开关状态,通通都属于汽车的state(状态)。

司机可以通过自己的操作来改变汽车的state,从而在仪表盘上实时显示全新的state。例如,当司机踩下油门时,汽车的驾驶速度会提高,从而让车速表上的数字增加。当司机踩下刹车时,汽车的驾驶速度会降低,从而让车速表上的数字减少。

内部环境因素的变化也会改变汽车的state,并立即显示在仪表盘上。比如当汽车的燃油快耗尽时,燃油表的状态会从F(Full)变到E(Empty)。但是当司机给汽车加满油后,燃油表又会回到F。

另外一个例子则是”维护提示“灯。当汽车达到预设的驾驶历程后,汽车的状态从不需要维护转为需要维护保养,从而让这个灯开启。而一旦汽车完成维护保养,汽车的state再次转为不需要维护保养,从而让这个灯关闭。

以上关于汽车的所有state共同组成了一个更复杂的概念,state space(状态空间)。

单一按钮示例项目的state space

好了,回到我们当前的示例。

和刚才举的汽车例子相比,只有一个按钮的示例项目的state space显然要简单多了。

在此前的待办事务清单中,我们曾指出需要实现的第一个里程碑,也就是触碰按钮时出现一个警告提示。

当前的应用包含了两个状态:

1.欢迎:

只需要在界面上显示”Welcome to my first app!“

当用户打开应用后,即便什么也不做,也可以看到这行信息。

2.提示:

当用户触碰按钮后,就会看到这个提示信息。

如果用state diagram(状态图)的方式来表示,那么当前应用的状态空间可以这样来表示:

其中不同颜色的矩形代表了应用的两种不同状态。

箭头代表从一种状态切换到另一种状态,而箭头上的文字则是状态切换的原因。

1.从”欢迎“到”提示“:

当用户触碰”Hit me”按钮时,就会触发状态切换。

2.从”提示“到”欢迎“:

当用户dismiss了提示信息后,就会触发该状态切换。

SwiftUI和state space

在SwiftUI中编写用户界面的代码跟绘制刚才的状态图非常类似。

如果说应用的状态图中显示了所有可能的状态,以及状态之间的所有可能切换方式。

那么在SwiftUI应用的代码则包含了所有可能的界面布局,以及布局之间的过渡切换。

让我们回过头看看当前的用户界面相关代码:

struct ContentView: View {
    var body: some View {
        VStack {
           Text("2020年面对困难不要害怕,武汉加油!")
               .fontWeight(.black)
               .foregroundColor(.red)
           Button(action:
              {
                    print("这辈子都没见过这样的要求~")
           }) {
                    Text("过来打我啊")
           }
      }
   }
}

注意,ContentView的body属性定义了界面的整体布局。

目前body中包含了一个VStack,通过它将Text文本对象和Button按钮对象进行垂直排列。

当前的代码定义了Welcome”欢迎“状态下的界面布局,接下来我们需要编写关于Alert(提示)状态的相关代码。

不过在此之前,我们还需要明确应用的state状态。

使用变量代表应用的state

我们已经看到了body这个变量是如何定义”欢迎“状态下的界面布局,接下来需要为应用的状态创建一个单独的变量。

该变量需要保存两种信息:

1.其中一个信息代表应用没有显示提示信息的状态

2.另外一个信息代表应用显示了提示信息的状态。

对于此类信息的保存,我们用某种叫布尔变量的东西比较合适。

布尔变量只有两个值,true和false,也就是说是,不是。

关于布尔数学和布尔这个人,感兴趣的童鞋可以去搜索一下:

这里还有一个八卦,深度学习三巨头之一杰弗里.辛顿教授的曾祖母的父亲就是大名鼎鼎的乔治.布尔。

所以这个怎么喷呢?这恐怕就是传说中的科学贵族吧。

好了,不再八卦,回到我们的代码。

我们需要创建一个名为alertIsVisible的布尔类型变量,当应用刚启动时,提示框默认是不显示的,也就是alertIsVisible的初始值是false。

只有当用户触碰了按钮后,alertIsVisible的值才会更改为true,同时显示出对应的提示框信息。

更改刚才的代码如下:

struct ContentView: View {
 @State var alertIsVisible: Bool = false

    var body: some View {
        VStack {
           Text("2020年面对困难不要害怕,武汉加油!")
               .fontWeight(.black)
               .foregroundColor(.red)
           Button(action:
              {
                    print("这辈子都没见过这样的要求~")
           }) {
                    Text("过来打我啊")
           }
      }
   }
}

这里我们只添加了一行代码而已,

@State var alertIsVisible: Bool = false

这行代码的意思很简单,我们定义了一个名为alertIsVisible的变量,它属于Bool类型,它的初始值是false。

至于@State,是个新东西。通过这个让开发者知道,alertIsVisible变量用于存储应用的状态。同时,它还告诉Swift注意密切关注该变量的内容变化,从而执行对应的任务。

接下来我们需要添加代码,让alertIsVisible在按钮触碰时更改状态:

struct ContentView: View {
 @State var alertIsVisible: Bool = false

    var body: some View {
        VStack {
           Text("2020年面对困难不要害怕,武汉加油!")
               .fontWeight(.black)
               .foregroundColor(.red)
           Button(action:
              {
                    print("这辈子都没见过这样的要求~")
                    self.alertIsVisible = true //更改状态
           }) {
                    Text("过来打我啊")
           }
      }
   }
}

这里我们新增了的一行代码用于更改alertIsVisible变量的状态:

 self.alertIsVisible = true //更改状态

好吧,这里又冒出个self是什么东西?

alertIsVisible是ContentView对象的一种属性,如果在是对象的外面使用它,我们需要用ContentView.alertIsVisible这种形式。但现在我们就在ContentView对象内部使用它,所以就用self代替ContentView对象了。

显示其它状态下的布局

这里再次重复一下:在SwiftUi中,我们必须定义所有可能状态下的布局。

此前我们已经定义了Welcome状态下的界面布局,接下来需要定义Alert状态下的界面布局。

在这种状态下,我们只需要让提示对话框显示就好。好在Button对象有一个内置的alert()方法,可以让我们轻松完成这一工作。

接下来更改刚才的代码如下:

struct ContentView: View {
 @State var alertIsVisible: Bool = false

    var body: some View {
        VStack {
           Text("2020年面对困难不要害怕,武汉加油!")
               .fontWeight(.black)
               .foregroundColor(.red)
           Button(action:
              {
                    print("这辈子都没见过这样的要求~")
                    self.alertIsVisible = true //更改状态
           }) {
                    Text("过来打我啊")
           }
              .alert(isPresented: self.$alertIsVisible){
                    Alert(title: Text("你好"), 
                          message: Text("这样的要求不算奇怪"), 
                          dismissButton: .default(Text("太棒了!")))
                }
      }
   }
}

先不去管上面新添加代码的含义,先跑起来给自己点小小的成就感再说。

点击Xcode工具栏上的运行按钮,可以在模拟器上触碰按钮,看到类似下面的界面:

现在来看我们刚刚添加的代码:

 .alert(isPresented: self.$alertIsVisible){
 Alert(title: Text("你好"), message: Text("这样的要求不算奇怪"), dismissButton: .default(Text("太棒了!")))
 }

alert()是Button的一个方法,它用于向用户显示一个提示信息。该方法需要两个参数。所谓的参数,就是当我们需要让某个方法或函数执行某些特定任务时,向它提供的基本信息。

举个例子,如果我们让加法函数执行两个数字之和,那就要提供两个参数,也就是要相加的两个数字。

在这里,alert()方法也需要两个参数:

1.到布尔状态变量的绑定(或者说双向关联)

什么叫绑定,说直白点就是alertIsVisible变量的值和alert提示信息是关联在一起的。当我们把alertIsVisible的值更改为true时,就会自动显示alert提示信息。反过来,当用户关闭了提示信息后,alertIsVisible的值会自动更改为false。

所以alertIsVisible前面的$符号其实就是告诉Swift,这是个绑定型的变量。

2.Alert对象

其中定义了alert提示信息要显示的具体内容。

进一步往下分析,Alert对象由三部分组成:

1.title(标题)

也就是提示信息的标题,比如这里的”你好“。

2.message(信息主体)

也就是提示信息的主要内容,比如这里的”这样的要求不算奇怪“。

3.dismissButton(取消按钮)

提示信息不可能永远显示,用户需要通过某种方式让它消失,所以这里我们创建了一个显示内容为”太棒了!!!“的取消按钮。

好了,要完全看懂上面这些信息,对于新手小白来说还是有些困难的。

不管怎样,还是恭喜你!

因为到目前为止,从某种 意义上来说,你算是真正完成了自己的首个iOS应用!

虽然它很简陋,但是麻雀虽小五脏俱全,有显示有交互。

同时,在我们的待办清单上的第一个任务已经完成:

在界面上放置一个按钮,当用户触碰该按钮时显示一条提示信息。

如果你在学习的过程中遇到困难,可以参考我提示的完整示例代码。

艰难的学习之后,让我们享受一点小小的福利,然后准备开启全新的篇章。




About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK