swiftUI视图修改器(ViewModifier)解析

作为SwiftUI框架的核心概念之一,视图修改器(ViewModifier)为我们提供了一种优雅的方式来封装和重用视图的样式和行为。

这是视图修改器的源码

swift 复制代码
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
extension View {

    /// Applies a modifier to a view and returns a new view.
    ///
    /// Use this modifier to combine a ``View`` and a ``ViewModifier``, to
    /// create a new view. For example, if you create a view modifier for
    /// a new kind of caption with blue text surrounded by a rounded rectangle:
    ///
    ///     struct BorderedCaption: ViewModifier {
    ///         func body(content: Content) -> some View {
    ///             content
    ///                 .font(.caption2)
    ///                 .padding(10)
    ///                 .overlay(
    ///                     RoundedRectangle(cornerRadius: 15)
    ///                         .stroke(lineWidth: 1)
    ///                 )
    ///                 .foregroundColor(Color.blue)
    ///         }
    ///     }
    ///
    /// You can use ``modifier(_:)`` to extend ``View`` to create new modifier
    /// for applying the `BorderedCaption` defined above:
    ///
    ///     extension View {
    ///         func borderedCaption() -> some View {
    ///             modifier(BorderedCaption())
    ///         }
    ///     }
    ///
    /// Then you can apply the bordered caption to any view:
    ///
    ///     Image(systemName: "bus")
    ///         .resizable()
    ///         .frame(width:50, height:50)
    ///     Text("Downtown Bus")
    ///         .borderedCaption()
    ///
    /// ![A screenshot showing the image of a bus with a caption reading
    /// Downtown Bus. A view extension, using custom a modifier, renders the
    ///  caption in blue text surrounded by a rounded
    ///  rectangle.](SwiftUI-View-ViewModifier.png)
    ///
    /// - Parameter modifier: The modifier to apply to this view.
    @inlinable nonisolated public func modifier<T>(_ modifier: T) -> ModifiedContent<Self, T>
}

首先要明确ViewModifier协议

swift 复制代码
@MainActor @preconcurrency
public protocol ViewModifier {
    associatedtype Body : View

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

    typealias Content
}

可以看出,必须有一个要修改的视图和修改的方法。

下面是一个推荐的示例

1 视图样式定义

swift 复制代码
struct BorderedCaption: ViewModifier {
    func body(content: Content) -> some View {
        content
            .font(.caption2)
            .padding(10)
            .overlay(
                RoundedRectangle(cornerRadius: 15)
                    .stroke(lineWidth: 1)
            )
            .foregroundColor(Color.blue)
    }
}

2 添加到视图view中,作为view的扩展

这样应用中的所有视图都可以像普通样式一样添加

swift 复制代码
extension View {
    func borderedCaption() -> some View {
        modifier(BorderedCaption())
    }
}

3 应用修改器

swift 复制代码
Image(systemName: "bus")
    .resizable()
    .frame(width:50, height:50)
Text("Downtown Bus")
    .borderedCaption()

如果你需要传递参数:

swift 复制代码
struct CustomPadding: ViewModifier {
    let amount: CGFloat
    
    func body(content: Content) -> some View {
        content.padding(amount)
    }
}

extension View {
    func customPadding(_ amount: CGFloat) -> some View {
        modifier(CustomPadding(amount: amount))
    }
}

其实SwiftUI 中每个 .padding(), .background(), .foregroundColor() 其实都是 视图修饰器 (modifier)

官方地址:developer.apple.com/documentati...

相关推荐
38242782719 小时前
JS表单提交:submit事件的关键技巧与注意事项
前端·javascript·okhttp
Kagol19 小时前
深入浅出 TinyEditor 富文本编辑器系列2:快速开始
前端·typescript·开源
小二·19 小时前
Python Web 开发进阶实战:Flask-Login 用户认证与权限管理 —— 构建多用户待办事项系统
前端·python·flask
浩瀚之水_csdn19 小时前
python字符串解析
前端·数据库·python
全栈小519 小时前
【前端】在JavaScript中,=、==和===是三种不同的操作符,用途和含义完全不同,一起瞧瞧
开发语言·前端·javascript
如果你好19 小时前
Vue createRenderer 自定义渲染器从入门到实战
前端·javascript·vue.js
温宇飞20 小时前
Web 图形合成技术:Blending 与 Porter-Duff Compositing
前端
小高00720 小时前
读懂 Tailwind v4:为什么它是现代前端项目的必选项?
前端·javascript·vue.js
我的golang之路果然有问题20 小时前
python中 unicorn 热重启问题和 debug 的 json
java·服务器·前端·python·json
SpringLament20 小时前
从零打造AI智能博客:一个项目带你入门全栈与大模型应用开发
前端·aigc