1 什么是some
在今年的WWDC上,苹果新推出的SwiftUI中出现了新的关键字some
这里的some其实就是和一个称为opaque(不透明)类型有关,在返回类型前面加上一些关键字表示返回类型是不透明的,不透明类型通常被称为反向泛型类型。
2 什么是泛型和some的作用
当你想声明使用多种类型的函数时,泛型类型基本上就是一个占位符,举个例子,max函数,取出两个数字的最大值,我们使用到了未知类型T
这里如果要比较大小,必须限定T支持比较操作,所以限定约束条件T:Comparable
在使用的时候编译器可以通过函数参数来推断T是什么类型
我们定义一个SurpriseEgg协议,具有关联类型ContentType,并且创建改类型的具体类型。
现在假如我们实现一个方法去抽取蛋,但是我们不知道具体是那种蛋,因为他可能是Puzzle、ToyEgg和FigureEgg中任何一种,因为他肯定是某种彩蛋(SupriseEgg)
这不会在 Swift中编译,因为swift不能把带有关联类型的协议类型作为返回类型。
这个时候就可以使用some关键字
添加这个关键字代表,你和编译器都确定这个函数总会返回一个特定的具体类型-只是你不知道是哪一种
3 这样做有什么用处?
使用不透明类型有两个很重要作用
1 返回关联类型的协议类型
现在我们可以从函数返回一个protocol,protocol中带有一个associated 类型,在以前的版本中,swift不允许我们把具有关联类型的协议作为返回类型。
这种写法是可以的,
带有关联类型的不可以作为返回类型
协议中使用Self关键字的也是不可以作为返回类型
都需要增加some关键字
2 SwiftUI中的不透明类型
SwiftUI的强大之处在于它的可组合性。通常,您可以使用堆栈视图和其他容器(如列表)从其他视图组成布局。这些容器都是通用类型,每次添加,删除,移动或替换视图时,它们的具体类型都会更改。例如,让我们看看以下简单的自定义视图:
这个类型some View 可以被推断未 VStack<TupleView<(Text, Image)>>
如果没有some关键字,我们必须这样写
如果我们需要加一个文本Text,那就需要改写返回值
这已经很烦人了。但最有可能的是,我们将使用多个容器。我们可能希望将堆栈嵌套在另一个堆栈中,也可能是列表中的其他堆栈。突然,我们身体的具体类型看起来像这样
List <Never,TupleView <(HStack <TupleView <(VStack <TupleView <(Text,Text)>>,Text)>>,HStack <TupleView <(VStack <TupleView <(Text,Text)>>,Text)>> )>>
你可能会同意这没有任何意义。更改层次结构中的单个视图时更新此类型非常繁琐。最重要的是,类型根本不可读。我们的思想无法在合理的时间内处理它,我们关心的实际上就是body返回some View。
这正是Apple为什么在他们的教程中使用不透明视图类型以及为什么你应该总是这样做的原因: