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...

相关推荐
我命由我123455 小时前
CesiumJS 笔记 - 获取容器中心点、Cartesian3 clone 方法、修改 Cartesian3 对象的高度
前端·javascript·css·前端框架·html·html5·js
Hopebearer_6 小时前
页面突然只剩 DOM?一次静态资源版本错配排查
前端·部署
东风破_6 小时前
ESLint 是什么?为什么你的项目需要它?
前端·后端·代码规范
圣殿骑士-Khtangc8 小时前
Go字符串高效拼接性能对比与底层原理分析
服务器·前端·golang
BigTopOne9 小时前
【ijkplayer】 硬解码流程
前端
kyriewen9 小时前
DeepSeek Harness开源第一天我就上手了——和Claude Code的差距比想象中大
前端·ai编程·deepseek
捡田螺的小男孩9 小时前
什么是 Skill?手把手带你写一个简单有用的 Skill!
前端·后端·程序员
IT_陈寒9 小时前
Redis集群这个坑,差点让我通宵
前端·人工智能·后端
90后的晨仔10 小时前
uni-app 路由跳转与页面导航 —— 终极详解(对标 iOS / Android / 鸿蒙三端原生)
前端
Heo10 小时前
大厂前端调试不能只会debugger
前端·javascript·面试