[SwiftUI 100 天] iExpense - part1

2020/3/18 23:01:51

本文主要是介绍[SwiftUI 100 天] iExpense - part1,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

iExpense 介绍

我们接下来的两个项目会把你的 SwiftUI 技术带向更高的水平,超越基础。因为我们会探索有多屏界面的 app ,能够加载和保存用户数据,并且 UI 更加灵活。

这头一个项目叫 iExpense ,它的功能是追踪花销,把个人花费和商务花费分隔开。实现这个 app 的过程中我们会学习到:

  • 呈现和消除新的界面
  • 从列表中删除行
  • 保持和加载用户数据

等等。

有不少要做的事情,让我们开始吧:用 Single View App template 创建新 iOS app ,取名“iExpense” 。这是我们的主工程,但开始这个工程之前我们需要先学习一些会用到的新技术。



为什么 @State 只能在结构体中工作?

用 @ObservedObject 共享 SwiftUI 的状态

请移步阅读 

https://juejin.im/post/5e683592e51d4526f16e5d13



译自 Showing and hiding views

显示和隐藏视图

在 SwiftUI 中,显示视图有几种方式,其中最常见的一种是 sheet :它是一种在已有视图之上呈现的新视图。在 iOS 上,这种视图给到我们的是一个像卡片一样的呈现:当前视图向后滑出一段距离,新视图以动画方式出现在当前视图的上面。

Sheets 工作方式和 alerts 很像,相似之处在于我们不是通过像 mySheet.present() 这样的代码呈现它。相反,我们定义 sheet 应该显示的条件。当条件变为 true 或者 false 时,sheet 会相应地呈现或者消失。

让我们举例说明。这个例子使用 sheet 展示一个新视图。首先,我们需要创建一个希望在 sheet 中展示的视图,像这样:

struct SecondView: View {
    var body: some View {
        Text("Second View")
    }
}复制代码

上面这个视图没有什么特别之处 —— 它并不知道自己会被用作 sheet 显示,也不需要知道。

接下来我们创建初始视图,由它来展示第二个视图。我们尽量简单实现:

struct ContentView: View { 
    var body: some View {
        Button("Show Sheet") {
            // 显示 sheet
        }
    }
}复制代码

填充注释部分需要四个步骤,我们逐一拆解。

首先,我们需要某个状态来追踪 sheet 是否应该显示。跟 alerts 一样,这个状态可以是一个最简单的布尔型,把以下属性添加到 ContentView

@State private var showingSheet = false复制代码

其次,我们需要在按钮点击时触发那个状态,把 // show the sheet注释替换成下面的代码:

self.showingSheet.toggle()复制代码

第三,我们需要把 sheet 附着在视图层级的某个地方。如果你还记得,我们显示 alerts 是用 alert(isPresented:) ,用到一个对于状态的双向绑定。而我们用在 sheet 上的东西是一样的 sheet(isPresented:).

sheet() 是一个跟 alert()一样的 modifier ,所以我们可以把它添加到按钮:

.sheet(isPresented: $showingSheet) {
    // contents of the sheet
}复制代码

第四,我们需要确定 sheet 里要展示的东西。在例子中,我们已经知道要做什么:我们要创建并显示 SecondView 的实例。代码上就是 SecondView(),就这样。

所以,完成后的 ContentView 结构体应该是这样:

struct ContentView: View {
    @State private var showingSheet = false

    var body: some View {
        Button("Show Sheet") {
            self.showingSheet.toggle()
        }
        .sheet(isPresented: $showingSheet) {
            SecondView()
        }
    }
}复制代码

运行程序,点击按钮,你会看到我们的第二个视图从底部滑入上,而你可以通过往下拖拽把它关掉。

sheet 可以呈现任何的视图,所以我们可以调整 SecondView :

struct SecondView: View {
    var name: String

    var body: some View {
        Text("Hello, \(name)!")
    }
}复制代码

相应调整实例化的地方:

.sheet(isPresented: $showingSheet) {
    SecondView(name: "@twostraws")
}复制代码

现在 sheet 会呈现 “Hello, @twostraws” 。

Swift 在背后做了大量工作:在我们给SecondView 添加了一个名字属性,Swift 会确保代码中所有 SecondView()的实例都变成 SecondView(name: "some name"),然后才能编译通过。

在我们继续之前,我还有一个东西要演示,那就是如何关闭视图。是的,你发现通过通过向下扫的操作可以关掉 sheet ,不过有的时候我们会希望通过编程的方式关闭视图 —— 比如在点击某个按钮之后关闭某个视图。

对于这种需求,SwiftUI 给了我们两个选项。其中简单一些的选项是引入另一个属性包装器 —— 是的,SwiftUI 解决问题的方式经常就是引入一个新的属性包装器。

言归正传,这个包装器叫 @Environment,它让我们可以创建存储值的属性,这种属性可以提供给外部使用。用户是处于 light mode 还是 dark mode ?用户是设置的更小的字号还是更大的字号?用户当前处于什么时区?所有这些值都来自环境,在我们的案例中,我们将从环境中读取视图的 presentation mode

一个视图的 presentation mode 包含两部分数据,两部分都有用:其一是存储视图当前是否呈现在屏幕上的属性,其二是一个可以给我们关闭视图的方法。

把这个属性添加到 SecondView,下面的代码会创建一个叫presentationMode的属性,并且绑定到 app 的环境中的 presentation mode 变量:

@Environment(\.presentationMode) var presentationMode复制代码

现在把 SecondView中的文本视图替换成下面的按钮:

Button("Dismiss") {
    self.presentationMode.wrappedValue.dismiss()
}复制代码

这里面的 wrappedValue 是必须的,因为 presentationMode 实际上是一个由系统自动更新的绑定 —— 我们需要扒开它的外衣,从中查找实际的 presentation mode 的状态值,作为关闭视图的条件。

有了这个按钮,你会发现现在可以通过按钮点击来显示和隐藏 sheet 了。

我的公众号 这里有Swift及计算机编程的相关文章,以及优秀国外文章翻译,欢迎关注~





这篇关于[SwiftUI 100 天] iExpense - part1的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程