Was wondering how it's possible to create modifiers for Swift UI views?
For example, let's say I have some view defined as so:
struct LabelView: View {
let font1: Font = .header
let font2: Font = .body
var body: Some View {
// two views, where one uses font1 and other uses font2
}
}
How would it be possible to create a modifier that allows something like:
LabelView()
.font1(.callout)
.font2(.body)
I'm trying to learn how to write API's in the declarative nature that Apple is pushing with Swift UI but it seems like documentation isn't complete on this. I've tried creating some sort of ViewModifier
type but I'm not really sure what I need to do with this, since it required I return _ModifiedContent<_, _>
and not exactly sure how to do this. Basically, is it possible to modify the properties of a view using a declarative syntax like the ones in the built in SwiftUI views.
As dfd linked to in the comments, you can create custom modifiers that use apple's provided modifiers. You can also create your own methods that modify var
s though.
Note: You can't use mutating methods here because function builders return immutable values. You'll get a compiler error. You need to make a copy of self
and return that.
extension LabelView {
func font1(_ font1: Font) -> Self {
var copy = self
copy.font1 = font1
return copy
}
}
You can also create a generic version that updates variables using a keypath:
extension View {
func modifying<T>(_ keyPath: WritableKeyPath<Self, T>, value: T) -> Self {
var copy = self
copy[keyPath: keyPath] = value
return copy
}
}
Usage of both versions:
struct LabelView: View {
var font1: Font = .headline
var font2: Font = .body
var body: some View { ... }
}
LabelView()
.modifying(\.font2, value: .callout)
.font1(.largeTitle)
And here is the result:
See if this is something you want. You can simply modify the properties according to your need. If you want a fixed textView, then keep it static in the custom labelView.
import SwiftUI
struct LabelView: View {
var font1: Font = .headline
var font2: Font = .subheadline
var text1: String = ""
var text2: String = ""
var body: some View {
VStack {
Text(text1).lineLimit(nil).font(font1)
Text(text2).lineLimit(nil).font(font2)
}
}
}
struct StackOverFlow : View {
var body: some View {
//LabelView(font1: .title, font2: .subheadline )
LabelView(font1: .title, font2: .subheadline, text1: "What is Lorem Ipsum?", text2: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.")
}
}