// it compiles without any problems, regardless ModifiedContent is not a View
func modify(with viewModifier: some ViewModifier) -> some View {
let content: ModifiedContent<Self, some ViewModifier> = modifier(viewModifier)
return content
}
Run Code Online (Sandbox Code Playgroud)
但如果我们以通用方式编写相同的内容,我们会收到预期的错误消息
func modify<V>(with viewModifier: some ViewModifier) -> V where V : View {
let content: ModifiedContent<Self, some ViewModifier> = modifier(viewModifier)
return content // error: Cannot convert return expression of type
// 'ModifiedContent<Self, some ViewModifier>' to return type 'V'
}
Run Code Online (Sandbox Code Playgroud)
这是您的第一份工作声明:
\n\n\nRun Code Online (Sandbox Code Playgroud)\nfunc modify(with viewModifier: some ViewModifier) -> some View\n
您some在该函数声明中使用了该关键字两次。重要的是要理解这在这两种用途中some意味着不同的事情。
在第一次使用 ( viewModifier: some ViewModifier) 中,some关键字是 \xe2\x80\x9c 语法糖\xe2\x80\x9d,用于隐式、未命名的泛型参数。我们可以通过将其替换为显式的、命名的泛型参数来对它的使用进行去糖化some,如下所示:
// Replace `some` in parameter position with an explicit generic parameter:\nfunc modify<VM: ViewModifier>(with viewModifier: VM) -> some View\nRun Code Online (Sandbox Code Playgroud)\n当您调用该modify方法时,您作为调用者选择一个实际类型来替换VM参数。所以你可以modify多次调用,VM每次都用不同的类型来替换。唯一的限制是替换类型必须始终符合ViewModifier协议。
some第一个函数声明中的第二次使用(in -> some View) 具有不同的含义。这意味着函数将返回一个类型符合 的值View,但具体类型由函数体选择。作为函数调用者,您不选择类型。
总结一下差异:
\nsome参数位置关键字
some返回类型位置的关键字
现在让我们看看第二个损坏的函数声明:
\n\n\nRun Code Online (Sandbox Code Playgroud)\nfunc modify<V>(with viewModifier: some ViewModifier) -> V where V : View\n
这与您的第一个函数声明类似,只是您已将some返回类型位置替换为泛型参数V。
问题是这些含义并不相同。正如我上面所解释的,返回类型some View意味着函数体选择实际类型,但泛型参数始终由函数的调用者选择。
这就是为什么当您的函数尝试执行此操作时会出现错误return content。无法保证具有contenttype V。您的函数对类型知之甚少V(您只知道它符合View),以至于该函数甚至无法创建类型值V(因为View协议没有任何init要求)。
您对第一个工作函数声明也有这样的评论:
\n\n\nRun Code Online (Sandbox Code Playgroud)\n// it compiles without any problems, regardless ModifiedContent is not a View\n
我假设您modify(withViewModifier:)在extension View. 这意味着Self符合View,所以ModifiedContent<Self, some ViewModifier>符合View。
| 归档时间: |
|
| 查看次数: |
468 次 |
| 最近记录: |