Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI custom Image Modifier

Tags:

ios

swift

swiftui

I am trying to create a custom image modifier that uses the resizable() function, therefore my content should be an Image. At least, that what I think so.

Error Message: Type 'IconModifier' does not conform to protocol 'ViewModifier'

struct IconModifier: ViewModifier {
    func body(content: Image) -> some View {
        content
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(width: 10, height: 10, alignment: .center)
    }
}
like image 414
Pondorasti Avatar asked Feb 02 '20 15:02

Pondorasti


People also ask

How do I create a custom view modifier in SwiftUI?

To create a custom modifier, create a new struct that conforms to the ViewModifier protocol. This has only one requirement, which is a method called body that accepts whatever content it's being given to work with, and must return some View .

What is a SwiftUI view modifier?

A modifier you can apply to a View or another ViewModifier . View modifiers essentially produce another version of the original view (A new version of the view is returned every time a modifier is applied). That makes it possible to add multiple paddings and background colors to a single view.

What is content SwiftUI?

The collection of underlying identified data that SwiftUI uses to create views dynamically. Current page is content.


1 Answers

Solution

You can just extend Image instead.

Used like so:

struct ContentView: View {

    var body: some View {
        VStack {
            Text("Hello World!")
            
            Image("someName")
                .imageIconModifier()
        }
    }
}

Image extension:

extension Image {
    
    func imageIconModifier() -> some View {
        self
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(width: 10, height: 10, alignment: .center)
    }
}

Why your solution wouldn't work

You first got the error:

Type 'IconModifier' does not conform to protocol 'ViewModifier'

This means that your IconModifier did not satisfy the requirements for the ViewModifier protocol, which if we see the definition:

func body(content: Self.Content) -> Self.Body

whereas you had:

func body(content: Image) -> Self.Body

which doesn't work. So next - we will change that to Content rather than Image:

Value of type 'IconModifier.Content' (aka '_ViewModifier_Content') has no member 'resizable'

This is basically saying that there is no .resizable() modifier for any View. The .resizable() modifier is inside defined inside only extension Image, and so no other View has this modifier.

And that is the core problem - the can't access the original View (Image for what we want) through the content parameter in a ViewModifier.

This is why I just made an extension for Image.

Hope this explanation helps!

like image 152
George Avatar answered Sep 20 '22 12:09

George