轻学编程|Swift 教程 011:名言轮播
轻学编程|Swift 教程 011:名言轮播

轻学编程|Swift 教程 011:名言轮播

本节课,我们将实现一个”名言轮播”的功能,并深入学习数组(Array)和条件判断语句(if-else)等 Swift 基础知识。

我们将展示如何保存多个名言,并通过按钮交互实现名言的循环轮播。

显示名言

首先,我们需要在 SwiftUI 中显示一条名言。

最简单的方式是使用 Text 视图:

Text("Slow progress is still progress.")

这个代码只能显示一条固定的名言。如果想要展示多条名言并实现切换功能,我们需要将名言保存起来。

但是,常规的字符串变量只能保存一条名言:

let sayings = "Slow progress is still progress."

如果需要保存多条名言,就需要为每一条名言声明一个变量:

let saying1 = "Slow progress is still progress."
let saying2 = "Difficult roads lead to beautiful destinations."
let saying3 = "Awake minds are the strongest."
let saying4 = "Long-term thinking wins over short-term tricks."
let saying5 = "Master one thing, and do it well."

但在实际开发中,这种做法不仅繁琐,而且由于每个变量都是独立的,我们无法实现灵活的轮播切换。

为了方便管理多条名言,我们需要使用一个数据结构,将它们存储在一起,这就是数组(Array)。

使用数组后,上述代码可以被保存为:

let sayings = [
    "Slow progress is still progress.",
    "Difficult roads lead to beautiful destinations.",
    "Awake minds are the strongest.",
    "Long-term thinking wins over short-term tricks.",
    "Master one thing, and do it well."
    ]

提示:在编程规范中,存储多个元素的数组变量名通常使用复数形式,如 sayings,以体现其集合的特征。

数组

在 Swift 中,数组是存储有序元素的集合,使用方括号 [] 表示。

[]

数组内部可以包含多个相同类型的元素,元素之间使用英文逗号 , 分隔。

例如:

[101, 102, 103, 104, 105]

可以把数组简单的理解为一列火车:

整列火车代表这个数组对象,每节车厢按照先后顺序排列。

索引和元素访问

因为数组是有序的,系统可以根据先后顺序定位数组的具体元素。这种定位机制被称为索引(Index)。

在 Swift(以及绝大多数编程语言)中,数组的索引是从 0 开始计算的,而不是 1。这意味着数组中的第一个元素对应的索引是 0,第二个元素是 1,以此类推。

如果要访问数组中的特定元素,只需在数组名称后加上方括号,并在其中填入目标元素的索引值。

例如:

sayings[0]   // 101
sayings[1]   // 102

如果尝试访问一个超出数组有效范围的索引,会发生“索引越界”(Index Out of Range)的问题。因此,在访问数组时要小心,确保索引在有效范围内。

索引越界

例如,当数组只有 5 个元素时,合法的索引范围是 0 到 4。如果我们尝试访问 sayings[5],程序将无法找到对应的“车厢”,从而引发“索引越界”错误,导致应用崩溃。

操作数组

数组不仅支持静态定义,还支持添加、删除、修改元素等操作,还可以获取数组的长度。

提示:如果需要修改数组,必须使用 var 声明变量,而不是 let 常量。

1. 新增元素

可以使用 append 方法在数组末尾添加元素:

var num = [0, 1, 2]
num.append(3)   // [0, 1, 2, 3]

2. 删除元素

通过 remove(at:) 方法,可以删除数组中的指定元素:

var num = [0, 1, 2]
num.remove(at: 0)   // [1, 2]

3. 修改元素

直接使用索引对数组元素进行修改:

var num = [0, 1, 2]
num[1] = 4   // [0, 4, 2]

4. 统计数组长度

使用 count 属性获取数组的元素个数:

var num = [0, 1, 2]
num.count   // 3

使用数组显示名言

为了显示多个名言,我们可以把名言保存到数组中,然后通过索引访问并显示。

首先,在 ContentView 中创建一个 sayings 数组来存储名言,然后在 Text 视图中通过索引读取并显示对应的名言:

struct ContentView: View {
    let sayings = [
        "Slow progress is still progress.",
        "Difficult roads lead to beautiful destinations.",
        "Awake minds are the strongest.",
        "Long-term thinking wins over short-term tricks.",
        "Master one thing, and do it well."
    ]
    
    var body: some View {
        VStack {
            Text(sayings[0])
        }
        .padding()
    }
}

在这里,sayings[0] 表示数组中的第一个名言。

如果想要显示不同的名言,只需要修改方括号内的索引值:

Text(sayings[0]) // "Slow progress is still progress."
Text(sayings[1]) // "Difficult roads lead to beautiful destinations."

定义名言的索引

为了实现名言的动态切换效果,我们不能在把索引“写死”在 Text 视图中。

我们需要创建一个变量,单独保存当前显示的索引值。

在 SwiftUI 中,我们可以使用 @State 声明一个可变的索引:

@State private var index = 0

SwiftUI 会监听 @State 包装的变量,当 index 发生变化时,SwiftUI 会重新渲染视图,并显示对应的名言。

接着,我们使用 sayings[index] 动态获取数组中的名言:

struct ContentView: View {
    @State private var index = 0
    let sayings = [
        "Slow progress is still progress.",
        "Difficult roads lead to beautiful destinations.",
        "Awake minds are the strongest.",
        "Long-term thinking wins over short-term tricks.",
        "Master one thing, and do it well."
    ]
    
    var body: some View {
        VStack {
            Text(sayings[index])
        }
        .padding()
    }
}

当 index 值发生变化时,Text 会显示不同的名言。

使用按钮控制索引

为了控制名言的切换,我们可以使用 Button 来修改 index 值。每次点击按钮,index 自动加 1:

Button("Next") {
    index += 1
}

当我们点击按钮时,index 的值会从 0 变成 1,触发视图刷新,Text(sayings[index]) 就会读取下一句名言。

然而,这里有一个潜在的问题:如果连续点击按钮,index 会递增到一个超出数组范围的值,这会导致数组索引越界错误。例如,当 index 达到 5(数组索引范围是 0 到 4)时,程序会崩溃。

为了防止数组索引越界,我们需要引入条件控制,确保 index 不会超出数组的范围。可以通过 if-else 语句来判断 index 是否小于数组的长度。

条件控制:if-else 语句

if-else 语句是 Swift 中最常用的条件分支语句,用于判断条件是否成立,并根据条件的真假执行不同的代码块。

基本结构:

if condition {
    // 当 condition 为 true 时执行的代码
} else {
    // 当 condition 为 false 时执行的代码
}

在 if 语句中,条件 condition 是一个布尔值(Bool 类型),可以是 true 或 false。当条件为 true 时,会执行 if 部分的代码,否则执行 else 部分的代码。

例如:

let age = 25
if age > 18 {
    print("Big Boy")
} else {
    print("Little Body")
}

这个示例中,age 的值是 25,if 语句判断 age > 18 是否成立,条件成立则输出 “Big Boy”。

如果不需要 else 部分的代码,可以省略:

if condition {
    // 当 condition 为 true 时执行的代码
}

使用条件控制索引范围

为防止数组索引越界,可以使用 if 语句来确保 index 不会超出数组的范围:

Button("Next") {
    if index < sayings.count - 1 {
        index += 1
    }
}

逻辑分析:sayings.count 的值为 5(共有 5 条名言),所以 sayings.count – 1 的值为 4,这也是数组的最后一个有效索引。

当 index 小于 4 时,点击按钮执行加 1 的操作是安全的;一旦 index 达到 4,条件不再满足,点击按钮就不会发生任何反应。

现在,代码已经实现了名言切换的功能:

struct ContentView: View {
    @State private var index = 0
    let sayings = [
        "Slow progress is still progress.",
        "Difficult roads lead to beautiful destinations.",
        "Awake minds are the strongest.",
        "Long-term thinking wins over short-term tricks.",
        "Master one thing, and do it well."
    ]
    var body: some View {
        VStack {
            Text(sayings[index])
            Button("Next") {
                if index < sayings.count - 1 {
                    index += 1
                }
            }
        }
        .padding()
    }
}

循环名言

如果我们希望在显示到最后一个名言后,点击按钮时重新显示第一个名言,从而实现名言的循环显示,可以通过 else 部分来实现:

Button("Next") {
    if index < sayings.count - 1 {
        index += 1
    } else {
        index = 0
    }
}

当点击按钮时,如果 index 达到数组的最后一个元素,index 会重置为 0,开始循环显示名言。

优化名言视图

现在,我们的名言轮播逻辑已经实现,但我们还可以进一步优化界面,使其更美观。

完整代码:

struct ContentView: View {
    @State private var index = 0
    let sayings = [
        "Slow progress is still progress.",
        "Difficult roads lead to beautiful destinations.",
        "Awake minds are the strongest.",
        "Long-term thinking wins over short-term tricks.",
        "Master one thing, and do it well."
    ]
    var body: some View {
        VStack(spacing: 10) {
            Text(sayings[index])
                .padding(20)
                .background(.white)
                .cornerRadius(10)
                .opacity(0.8)
            Button("Next") {
                if index < sayings.count - 1 {
                    index += 1
                } else {
                    index = 0
                }
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()
        .background(
            Image("001")
        )
    }
}

在这个示例中,Text 视图添加了一个白色半透明背景和圆角,Button 按钮使用 .borderedProminent 样式,VStack 设置了背景图片。

知识点补充:在使用 background() 修饰符在处理图像背景时,其默认行为是尽可能填满当前视图所在的布局区域。在很多情况下,它能够自然地延伸覆盖至安全区域(Safe Area)。

现在,我们就实现了名言轮播的视图。

总结

通过本节课的学习,我们掌握了如何使用数组来存储多个名言,并通过 if 和 if-else 语句来实现名言的轮播。

我们还了解了数组的基本操作,如新增、删除、修改元素,以及如何防止数组索引越界。

这节课不仅讲解了名言轮播的功能实现,还结合了数组和条件语句的基本用法,帮助我们掌握了处理数据和控制程序流程的能力。

扩展知识 – 多重条件判断: if-else if-else 语句

在实际开发中,常常需要处理多个条件。比如,在某款游戏中,当积分等于 1 时触发事件 A,等于 2 时触发事件 B,等于 3 时触发事件 C,以此类推。

面对超过两个条件分支的场景,我们就需要使用 if-else if-else 语句来进行多重判断。

基本语法:

if conditionA {
    // 当 conditionA 为 true 时执行的代码
} else if conditionB {
    // 当 conditionB 为 true 时执行的代码
} else if conditionC {
    // 当 conditionC 为 true 时执行的代码
} else {
    // 所有条件均不满足时执行的代码
}

在这种情况下,程序会按照顺序检查条件,并执行第一个满足的条件。如果没有条件满足,就会执行 else 后面的代码。

在名言轮播中,我们也可以使用 if-else if-else 语句进行多重判断:

Button("Next") {
    if index == 0 {
        index += 1
    } else if index == 1 {
        index += 1
    } else if index == 2 {
        index += 1
    } else if index == 3 {
        index += 1
    } else if index == 4 {
        index = 0
    } else {
        index = 0
    }
}

当 index 为 0、1、2、3 时,每次点击按钮执行 index += 1,当 index 为 4(最后一个元素)时,将 index 重置为 0,实现循环。

else 分支用于兜底,防止出现非法值(例如 index 被错误修改)。

需要注意的是,这里使用的 == 表示判断”是否相等”,如果 if 语句判断 index 和某个数字相等,则返回 true 并执行后面的代码块。如果不相等,则继续下一个 if 语句的判断。

这种多重判断有利于在不同的条件场景中,执行不同的代码。

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注