为什么 resizeable() 需要成为视图中的第一个方法?

Why does resizeable() need to be the first method in a View?

在此处使用 XCode11 beta 4:

为什么要先列出 .resizable() 方法才不会导致 Canvas 崩溃?

例如:

有效

struct CircleImage: View {
    var body: some View {
        Image("Pizza")
            .resizable()
            .scaledToFit()
            .clipShape(Circle())
            .overlay(
                Circle()
                    .stroke(Color.gray, lineWidth: 4)
            )
        .shadow(radius: 10)
    }

}

不起作用

struct CircleImage: View {
    var body: some View {
        Image("Pizza")            
            .scaledToFit()
            .resizable()
            .clipShape(Circle())
            .overlay(
                Circle()
                    .stroke(Color.gray, lineWidth: 4)
            )
        .shadow(radius: 10)
    }

}

该错误似乎具有误导性:

Value of type 'some View' has no member 'resizable'

我同意 SwiftUI 中很多时候的编译错误非常具有误导性。但在这种情况下,它不是。

查看resizable()scaledToFit()的声明:

extension View {
    @inlinable public func scaledToFit() -> some View
}
extension Image {
    public func resizable(capInsets: EdgeInsets = EdgeInsets(), resizingMode: Image.ResizingMode = .stretch) -> Image
}

scaledToFit()是View的扩展。这意味着您可以使用它来修改任何视图。而resizable()是Image的扩展,所以只能用在Image上。

并且因为 scaledToFit() returns some View,从技术上讲它不再是图像。这意味着您不能对其调用 .resizable()

.font().fontWeight() 也会发生同样的事情。它们只能应用于 Text,反过来它们也适用于 return 文本。这意味着这些组合是有效的:

Text("hello").font(.title).fontWeight(.bold).frame(width: 300)
Text("hello").fontWeight(.bold).font(.title).frame(width: 300)

但这些不是:

Text("hello").font(.title).frame(width: 300).fontWeight(.bold)
Text("hello").frame(width: 300).fontWeight(.bold).font(.title)
Text("hello").fontWeight(.bold).frame(width: 300).font(.title)

因为 .frame() returns some View,您不能再使用 Text 特定修饰符。

现在再次查看您的错误消息:Value of type 'some View' has no member 'resizable'。就是说 some View 不知道 resizable,这是真的,只有 Image 知道。

声明已在 beta4 中清理。当视图被修改时,他们习惯于 return 一些非常长的类型,而不是 returning some View,例如:Self.Modified<_FrameLayout>Self.Modified<_AspectRatioLayout>