作为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()
///
/// 
///
/// - 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)