SwiftUI:为什么ModifiedContent符合'some View'函数返回类型?

vcudknz3  于 2023-01-29  发布在  Swift
关注(0)|答案(3)|浏览(254)
// 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'
}
mrwjdhj3

mrwjdhj31#

下面是您的第一个工作声明:

func modify(with viewModifier: some ViewModifier) -> some View

你在函数声明中两次使用了some关键字,理解some在这两次使用中的意思不同是很重要的。
在第一次使用(viewModifier: some ViewModifier)中,some关键字是一个隐式的、未命名的泛型参数的“语法糖”,我们可以通过将其替换为一个显式的、命名的泛型参数来对some的使用进行去糖处理,如下所示:

// Replace `some` in parameter position with an explicit generic parameter:
func modify<VM: ViewModifier>(with viewModifier: VM) -> some View

当你调用modify方法时,你作为调用者选择一个真实的类型来替换VM参数,所以你可以多次调用modify,每次用不同的类型来替换VM,唯一的约束是替换类型必须始终符合ViewModifier协议。
在第一个函数声明(在-> some View中)中第二次使用some有不同的含义。它意味着函数将返回一个类型符合View的值,但具体类型由函数体选择。作为函数调用者,您选择类型。
总结差异:

  • 参数位置中的some关键字
  • 表示隐式的未命名泛型类型参数;
  • 可以在不更改函数体的情况下将其解糖为显式的命名泛型参数;
  • 替换为函数调用方选择的类型。
  • 返回类型位置中的some关键字
  • 表示已知符合协议的类型;
  • 是由函数体选择的类型。

现在让我们看一下第二个被破坏的函数声明:

func modify<V>(with viewModifier: some ViewModifier) -> V where V : View

这类似于您的第一个函数声明,不同之处在于您将返回类型位置中的some替换为泛型参数V
问题是这两个参数的含义不同,正如我前面解释的,返回类型some View意味着函数体选择实际类型,但是泛型参数总是由函数调用者选择。
这就是为什么当你的函数尝试return content时会得到这个错误。不能保证contentV类型。你的函数对V类型知之甚少(您只知道它符合View),该函数甚至无法创建V类型的值(因为View协议没有任何init要求)。
在第一个函数声明中也有这样的注解:

// it compiles without any problems, regardless ModifiedContent is not a View

我假设您在extension View中声明了modify(withViewModifier:)方法,这意味着Self符合View,因此ModifiedContent<Self, some ViewModifier>符合View

o4tp2gmn

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

wrrgggsh

wrrgggsh3#

感谢@robmayoff和@jrturton,我终于明白了,ModifiedContent符合some View是因为ModifiedContent有条件地符合View,我们可以通过观察ModifiedContent的定义来确定这一点,如果向下滚动,我们可以看到:

extension ModifiedContent : View where Content : View, Modifier : ViewModifier { ... }

相关问题