SwiftUI:ViewModifier,其中内容是图像

SwiftUI:ViewModifier,其中内容是图像,swift,swiftui,swift-protocols,Swift,Swiftui,Swift Protocols,我收到一个错误“键入'PlayButtonModifier'不符合协议'ViewModifier'”,我不明白为什么,更重要的是,不知道如何正确操作 我只是尝试为图像创建一个视图修改器,这样我就可以在其上使用例如.resizeable(),它只在图像中定义 在ViewModifier协议中,定义了Content的Typealias。我的naiv认为这应该是可行的: struct PlayButtonModifier: ViewModifier { typealias Content =

我收到一个错误“
键入'PlayButtonModifier'不符合协议'ViewModifier'
”,我不明白为什么,更重要的是,不知道如何正确操作

我只是尝试为
图像
创建一个
视图修改器
,这样我就可以在其上使用例如
.resizeable()
,它只在
图像
中定义

ViewModifier
协议中,定义了
Content
Typealias
。我的naiv认为这应该是可行的:

struct PlayButtonModifier: ViewModifier {
    typealias Content = Image

    func body(content: Content) -> some View {
        content
    }
}
不,太容易了。结构的隐式类型别名也会发生同样的情况:

struct PlayButtonModifier: ViewModifier {
    func body(content: Image) -> some View {
        content
    }
}
同样的错误


这里怎么了?它的正确性如何?

感谢您的评论和讨论,我最终使用了以下代码片段。基本上,它是专门用于图像的
ViewModifier
的实现

protocol ImageModifier {
    /// `Body` is derived from `View`
    associatedtype Body : View

    /// Modify an image by applying any modifications into `some View`
    func body(image: Image) -> Self.Body
}

extension Image {
    func modifier<M>(_ modifier: M) -> some View where M: ImageModifier {
        modifier.body(image: self)
    }
}
我不是100%满意,因为必须定义修饰符以返回
某些视图
或返回
图像
。这两种情况都有缺点,不能与SwiftUI完美集成


当定义
ImageModifier
以返回
图像时,它减少了仅将图像修改为特定于图像的修改器的可能性(实际上
可调整大小()当定义它返回
some View
时,我不能链接
ImageModifier
s,因为第二个修饰符必须是
ViewModifier

在这种情况下,如果修改特定于特定的视图类型,
Image
也就是说,您可以直接在该视图类型上添加扩展:

extension Image {
    func myImageModifier() -> some View {
        self
            .resizable()
            .aspectRatio(1.0, contentMode: .fit)
            .clipShape(Circle())
   }
}
下面是一个完整的操场文本示例。如果你在游乐场“资源”文件夹“otter.png”中添加一张可爱的水獭图片,你会得到一个更漂亮的结果:)


这里的内容是不透明的typealias。。。这将帮助你澄清这个领域。嗨@Asperi,你链接背后的答案很好地解释了幕后发生的事情。谢谢你。现在有一个100万美元的问题:我如何使用它?苹果付出了所有的努力,甚至包括对Swift的语法修改,只是为了能够修改标准的普通视图?甚至连图片和文字都没有?我仍然相信,其中有一些东西,我只是还没有发现。所有修饰符实际上都是一个函数,即..resizeable()。ViewModifier是通用视图修改的通用机制。对于特定的修改,您可以创建特定的功能、可计算属性、专用视图等。唯一的一个要求是——这些应该生成一些视图作为输出。
extension Image {
    func myImageModifier() -> some View {
        self
            .resizable()
            .aspectRatio(1.0, contentMode: .fit)
            .clipShape(Circle())
   }
}
import PlaygroundSupport
import SwiftUI

let image = (UIImage(named: "Otter.png") ?? UIImage(systemName: "exclamationmark.square")!)

struct ContentView: View {
    var body: some View {
        VStack {
            Text("hello world")
            Image(uiImage: image)
                .myImageModifier()
        }
    }
}

extension Image {
    func myImageModifier() -> some View {
        self
            .resizable()
            .aspectRatio(1.0, contentMode: .fit)
            .clipShape(Circle())
    }
}

PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())