// 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
}
但如果我们以泛型方式编写相同的内容,则会收到预期的错误消息
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'
}
3条答案
按热度按时间mrwjdhj31#
下面是您的第一个工作声明:
你在函数声明中两次使用了
some
关键字,理解some
在这两次使用中的意思不同是很重要的。在第一次使用(
viewModifier: some ViewModifier
)中,some
关键字是一个隐式的、未命名的泛型参数的“语法糖”,我们可以通过将其替换为一个显式的、命名的泛型参数来对some
的使用进行去糖处理,如下所示:当你调用
modify
方法时,你作为调用者选择一个真实的类型来替换VM
参数,所以你可以多次调用modify
,每次用不同的类型来替换VM
,唯一的约束是替换类型必须始终符合ViewModifier
协议。在第一个函数声明(在
-> some View
中)中第二次使用some
有不同的含义。它意味着函数将返回一个类型符合View
的值,但具体类型由函数体选择。作为函数调用者,您不选择类型。总结差异:
some
关键字some
关键字现在让我们看一下第二个被破坏的函数声明:
这类似于您的第一个函数声明,不同之处在于您将返回类型位置中的
some
替换为泛型参数V
。问题是这两个参数的含义不同,正如我前面解释的,返回类型
some View
意味着函数体选择实际类型,但是泛型参数总是由函数调用者选择。这就是为什么当你的函数尝试
return content
时会得到这个错误。不能保证content
有V
类型。你的函数对V
类型知之甚少(您只知道它符合View
),该函数甚至无法创建V
类型的值(因为View
协议没有任何init
要求)。在第一个函数声明中也有这样的注解:
我假设您在
extension View
中声明了modify(withViewModifier:)
方法,这意味着Self
符合View
,因此ModifiedContent<Self, some ViewModifier>
符合View
。o4tp2gmn2#
ModifiedContent
是一个泛型视图,因此您可以将其作为不透明结果类型some View
返回。返回-> V where V : View
时,ModifiedContent
必须匹配从中调用它的任何V
类型,但这是不可能的。另见:https://forums.swift.org/t/how-to-use-a-generic-type-as-the-functions-return-type/37666/2
wrrgggsh3#
感谢@robmayoff和@jrturton,我终于明白了,
ModifiedContent
符合some View
是因为ModifiedContent
有条件地符合View
,我们可以通过观察ModifiedContent
的定义来确定这一点,如果向下滚动,我们可以看到: