Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

xcode

swiftui

Using XCode11 beta 4 here:

Why does the .resizable() method need to be listed first to not crash the Canvas?

For example:

Works

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

}

Doesn't Work

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

}

The error seems misleading:

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

like image 756
nipponese Avatar asked Sep 01 '25 15:09

nipponese


1 Answers

I agree that many times compile errors in SwiftUI are very misleading. But in this case, it is not.

Look at the declaration of resizable() and scaledToFit():

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

scaledToFit() is an extension of View. That means you can use it to modify any view. While resizable() is an extension of Image, so you can only use it on an Image.

And because scaledToFit() returns some View, it is no longer technically an Image. That means you cannot call .resizable() on it.

Same thing happens with .font() and .fontWeight(). They can only be applied to Text and in turn they also return Text. Which means these combinations are valid:

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

but these are not:

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)

Because .frame() returns some View, you can no longer use Text specific modifiers.

Now look at your error message again: Value of type 'some View' has no member 'resizable'. It is saying some View does not know resizable, and that is true, only Image does.

Declarations have been cleaned up in beta4. When a view was modified, instead of returning some View, they used to return some very long types, such as: Self.Modified<_FrameLayout> or Self.Modified<_AspectRatioLayout>

like image 103
kontiki Avatar answered Sep 04 '25 11:09

kontiki