“你不应该双手抓住捕手的手套度过一生-你必须能够向后扔东西。”

ForEach和List使用数字范围

正如我已经说过几次,当我们在一个循环中创建视图时,SwiftUI需要了解如何唯一地标识每个项目,以便它可以对来回的数据进行动画处理。这本身并不复杂,但是有一种特殊的用法会把人们拒之门外,这就是range。

首先,让我们看一些代码:

1
2
3
ForEach(0..<5) {
Text("Row \($0)")
}

从0到5循环播放,每次打印出一些文本。SwiftUI可以确保每个项目都是唯一的,因为它在一个范围内计数,并且范围没有重复的值。

实际上,如果你查看我们背后的SwiftUI代码,ForEach你会发现它实际上是这样的:

1
public init(_ data: Range<Int>, @ViewBuilder content: @escaping (Int) -> Content)

视图生成器(实际上是构成视图的东西)将从范围中获得一个整数,并有望发送回一些可以呈现的视图内容。

现在尝试编写以下代码:

1
2
3
ForEach(0...5) {
Text("Row \($0)")
}

从0 到 5 计数,这意味着它将创建六个视图。或至少它会创建六个视图(如果它确实起作用的话)–该代码无法编译。

再看一下ForEach想要的数据类型:Range<Int>。那是一个整数范围,但这是一个非常特定的范围–还有另一个非常相似的类型称为ClosedRange<Int>,这就是导致问题的原因。

当我们写的0..<5时候得到一个Range<Int>,但是当我们写的0…5时候得到一个ClosedRange<Int>。尽管它看起来与我们相似,但Swift认为这两个范围类型是不同的,因此我们不能将其与封闭范围一起使用ForEach-目前尚不可能,尽管我希望这会改变。

资源库的文件命名问题

在Word Scramble中,我们在包中查找了start.txt,然后将其加载以供游戏使用。然后我解释说,所有iOS,macOS,tvOS和watchOS应用程序都作为捆绑包出售,这些捆绑包将其二进制文件(已编译的Swift程序),其Info.plist,其资产目录等结合在一起。

我没有提到的一件事是这些捆绑包的构建方式,尤其是我想提及资产目录和松散文件。

首先,资产目录是我们一直在存储要在应用程序中使用的图像的位置,它们不仅仅是一种组织图片的理想方式。实际上,当Xcode构建我们的资产目录时,它会遍历我们所有的图片并针对iOS设备对其进行优化,然后将结果放入可以有效加载的已编译资产目录中。随着资产目录的进一步发展,你将了解到它们可以处理矢量资产,颜色,纹理等等,它们是多用途的东西!

其次,松散资产用于我们应用程序中的所有其他类型的媒体–文本文件,JSON,XML,电影等。如果你有很多这样的文件,则可以在Xcode内进行分组以组织它们,但是在构建时,一切都消失了:所有这些文件都放入一个称为资源目录的目录中。发生这种情况的原因是,当我们要求捆绑包查找“ start.txt”的URL时,它不需要搜索应用捆绑包中的所有目录,而是可以在一个位置查找,因为所有文件都在那里。

这会产生一个有趣的问题,这是你早晚会遇到的问题:由于Xcode项目中所有地方的所有松散文件最终都放置在一个资源目录中,因此你无法在任何地方两次使用相同的资产文件名在你的项目中。不管文件位于哪个组中,或者它们在Xcode项目中看起来有多远都没有关系:如果你的项目中有两个名为start.txt的文件,则构建将失败,因为Xcode无法将它们都放入同一目录。

参考资料

查看下一天的SwiftUI学习笔记

关于100days英文课程