新的SwiftUI教程有以下代码:
struct ContentView: View {
var body: some View {
Text("Hello World")
}
}
第二行是单词some,在他们的网站上突出显示,就好像它是一个关键字一样。
Swift 5.1似乎没有把some作为关键字,而且我不知道some这个词还能在那里做什么,因为它在类型通常的位置。有没有一个新的、未公布的Swift版本?它是一个我不知道的被用在类型上的函数吗?
关键字有的作用是什么?
'some'表示不透明类型。在SwiftUI中,View被声明为一个协议
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol View {
/// The type of view representing the body of this view.
///
/// When you create a custom view, Swift infers this type from your
/// implementation of the required `body` property.
associatedtype Body : View
/// Declares the content and behavior of this view.
var body: Self.Body { get }
}
当你将视图创建为Struct时,你要遵守视图协议,并告诉var主体将返回一些将确认视图协议的内容。它就像一个通用的协议抽象,你不必定义具体的类型。
Swift 5.1 (Swift -evolution提议)中的some关键字与协议一起作为返回类型使用。
Xcode 11发布说明是这样的:
函数现在可以通过声明它遵循什么协议来隐藏具体的返回类型,而不是指定确切的返回类型:
func makeecollection () -> some Collection {
返回[1,2,3]
}
调用该函数的代码可以使用协议的接口,但不能看到底层类型。(se - 0244, 40538331)
在上面的例子中,你不需要告诉你将返回一个Array。这甚至允许您返回一个只符合Collection的泛型类型。
还要注意你可能会遇到的这个错误:
'some'返回类型仅在iOS 13.0.0或更新版本中可用
这意味着你应该使用可用性来避免一些在iOS 12和之前的版本:
@available(iOS 13.0, *)
func makeACollection() -> some Collection {
...
}
我将尝试用非常基本的实际示例回答这个问题(这是一个关于什么的不透明结果类型)
假设你有关联类型的协议,并且有两个结构实现它:
protocol ProtocolWithAssociatedType {
associatedtype SomeType
}
struct First: ProtocolWithAssociatedType {
typealias SomeType = Int
}
struct Second: ProtocolWithAssociatedType {
typealias SomeType = String
}
在Swift 5.1之前,下面是非法的,因为ProtocolWithAssociatedType只能用作泛型约束错误:
func create() -> ProtocolWithAssociatedType {
return First()
}
但在Swift 5.1中,这是可以接受的(一些人补充说):
func create() -> some ProtocolWithAssociatedType {
return First()
}
以上是实际使用,广泛用于SwiftUI的一些视图。
但有一个重要的限制-返回类型需要在编译时知道,所以下面的函数声明了一个不透明的返回类型,但其主体中的返回语句没有匹配的底层类型错误:
func create() -> some ProtocolWithAssociatedType {
if (1...2).randomElement() == 1 {
return First()
} else {
return Second()
}
}