我知道你们中的某些人可能会热衷于今天的Swift新学习,但请坚持:您刚刚完成了关于闭包的学习,那是一个困难的话题。然后您今天还能回来继续学习更多的内容,认真地说,这值得尊重。
而且我有一些好消息要给您。首先,我们不仅会在下周的巩固日再次讨论闭包问题,而且很快就会在实际的iOS项目中将它们付诸实践。因此,即使您不能100%地确定它们的工作原理或需要它们的原因,也将一清二楚——坚持下去!
无论如何,今天的话题是结构体。结构让我们从几个小类型中创建自己的数据类型。例如,您可以将三个字符串和一个布尔值放在一起,并说它代表您的应用程序中的用户。
这些自定义类型-用户,游戏,文档等——构成了我们构建软件的真正核心。如果您做对了,那么您的代码通常会遵循。
正如极具影响力的一本书《神话人月》(The Mythical Man-Month)的作者弗雷德·布鲁克斯(Fred Brooks)曾说过的那样:“机智的程序员……通常可以通过将自己与代码分离开来,回馈并考虑数据来做到最好。表示法是编程的本质。”
此外,结构体在SwiftUI中极为常见,因为我们设计的每段UI都是基于结构体构建的,内部包含许多结构体。学习起来并不难,但是公平地说,闭包之后几乎一切都变得容易了!
今天,您有7个一分钟的视频可供观看,并且您将学习如何创建自己的类型,添加属性,方法等。完成每个视频后,将进行简短测试,以确保您了解了所教的内容。
1. 创建自己的结构体 Creating your own structs – test
Swift可让您通过两种方式设计自己的类型,其中最常见的称为structures(结构体 ),或简称为struct
。可以给结构赋予它们自己的变量和常量以及它们自己的功能,然后根据需要创建和使用它们。
让我们从一个简单的示例开始:我们将创建一个Sport
结构体,将其名称存储为字符串。结构中的变量称为属性,因此这是具有一个属性的结构体:
struct Sport {
var name: String
}
定义了类型,所以现在我们可以创建和使用它的实例:
var tennis = Sport(name: "Tennis")
print(tennis.name)
我们将name
和tennis
变量都设置为变量,因此可以像常规变量一样更改它们:
tennis.name = "Lawn tennis"
属性可以像常规变量一样具有默认值,并且通常可以依靠Swift的类型推断。
2. 计算属性 Computed properties – test
我们刚刚创建了一个Sport
结构,如下所示:
struct Sport {
var name: String
}
那有一个存储字符串的name
属性。这些称为存储属性,因为Swift具有另一种称为计算属性的属性——一种运行代码以计算出其值的属性。
我们将向Sport
结构体添加另一个存储的属性,然后是一个计算的属性。外观如下:
struct Sport {
var name: String
var isOlympicSport: Bool
var olympicStatus: String {
if isOlympicSport {
return "\(name) is an Olympic sport"
} else {
return "\(name) is not an Olympic sport"
}
}
}
如您所见,olympicStatus
看起来像一个普通的String
,但是它会根据其他属性返回不同的值。
我们可以通过创建Sport
的新实例来进行尝试:
let chessBoxing = Sport(name: "Chessboxing", isOlympicSport: false)
print(chessBoxing.olympicStatus)
3. 属性观察器 Property observers – test
使用属性观察器,可以在任何属性更改之前或之后运行代码。为了说明这一点,我们将编写一个Progress
结构来跟踪任务和完成百分比:
struct Progress {
var task: String
var amount: Int
}
现在,我们可以创建该结构的实例并随时间调整其进度:
var progress = Progress(task: "Loading data", amount: 0)
progress.amount = 30
progress.amount = 80
progress.amount = 100
我们想要的是Swift每次amount
变化时都打印一条消息,我们可以使用didSet
属性观察器。每当amount
更改时,这将运行一些代码:
struct Progress {
var task: String
var amount: Int {
didSet {
print("\(task) is now \(amount)% complete")
}
}
}
您也可以使用willSet
在属性更改之前执行操作,但这很少使用。
4. 方法 Methods – test
结构体内部可以具有函数,并且这些函数可以根据需要使用结构体的属性。结构体内部的函数称为方法,但它们仍使用相同的func
关键字。
我们可以用City
结构体来证明这一点。这将具有一个population
属性,该属性存储城市中的人口数量,以及一个collectTaxes()
方法,该方法返回人口计数乘以1000。由于该方法属于City
,因此它可以读取当前城市的population
属性。
这是代码:
struct City {
var population: Int
func collectTaxes() -> Int {
return population * 1000
}
}
该方法属于该结构体,因此我们在该结构的实例上调用它,如下所示:
let london = City(population: 9_000_000)
london.collectTaxes()
5. Mutating方法 Mutating methods – test
如果结构体具有可变属性,但该结构的实例创建为常量,则该属性不能更改——该结构是常量,因此无论其创建方式如何,其所有属性也都是常量。
问题在于,在创建结构时,Swift不知道将其与常量还是变量一起使用,因此默认情况下采用安全方法:除非明确要求,否则Swift不会允许您编写更改属性的方法。
当您想在方法内部更改属性时,需要使用mutating
关键字对其进行标记,如下所示:
struct Person {
var name: String
mutating func makeAnonymous() {
name = "Anonymous"
}
}
因为它更改了属性,所以Swift仅允许在作为变量的Person
实例上调用该方法:
var person = Person(name: "Ed")
person.makeAnonymous()
6. 字符串的属性和方法 Properties and methods of strings – test
到目前为止,我们已经使用了很多字符串,事实证明它们是结构体——它们具有自己的方法和属性,可用于查询和操作字符串。
首先,我们创建一个测试字符串:
let string = "Do or do not, there is no try."
您可以使用其count
属性读取字符串中的字符数:
print(string.count)
它们具有hasPrefix()
方法,如果字符串以特定字母开头,则返回true
:
print(string.hasPrefix("Do"))
您可以通过调用字符串uppercased()
方法将字符串大写:
print(string.uppercased())
您甚至可以让Swift将字符串的字母排序成一个数组:
print(string.sorted())
字符串具有更多的属性和方法-尝试输入string
,调出Xcode的代码补全选项。
7. 数组的属性和方法 Properties and methods of arrays – test
数组也是结构体,这意味着它们也具有我们可以用来查询和操作数组的自己的方法和属性。
这是一个使我们开始的简单数组:
var toys = ["Woody"]
您可以使用其count
属性读取数组中的项目数:
print(toys.count)
如果要添加新项,请使用如下的append()
方法:
toys.append("Buzz")
您可以使用其firstIndex()
方法在数组内找到任何项目,如下所示:
toys.firstIndex(of: "Buzz")
这将返回1,因为数组从0开始计数。
就像使用字符串一样,您可以让Swift将数组中的项目按字母顺序排序:
print(toys.sorted())
最后,如果要删除项目,请使用remove()
方法,如下所示:
toys.remove(at: 0)
数组具有更多的属性和方法-尝试键入toys
,调出Xcode的代码补全选项。
网友评论