customized a property wrapper
Example: write the value to a file stored in iphone documents.
import SwiftUI
struct ContentView: View {
@Document("test.txt") var document
var body: some View {
NavigationView {
VStack {
// read
Text(document)
Button("Change document") {
document = String(Int.random(in: 1...1000))
}
// write
TextEditor(text: $document)
}
.navigationTitle("SimpleText")
}
}
}
@propertyWrapper struct Document: DynamicProperty {
@State private var value = ""
private let url: URL
init(_ filename: String ) {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
url = paths[0].appendingPathComponent(filename)
let initialText = (try? String(contentsOf: url)) ?? ""
print(initialText)
_value = State(wrappedValue: initialText)
}
var wrappedValue: String {
get {
value
}
nonmutating set {
do {
try newValue.write(to: url, atomically: true, encoding: .utf8)
value = newValue
} catch {
print("Failed to write output")
}
}
}
var projectedValue: Binding<String> {
Binding(
get: { wrappedValue },
set: { wrappedValue = $0 }
)
}
}
Example 1: simple illustration. It shows its relationship between property wrapper and @State. You can change value in projectedValue and you can pass variables in the init func.
struct ContentView: View {
@Document var document
var body: some View {
NavigationView {
VStack {
// read
Text(document)
Button("Change document") {
document = String(Int.random(in: 1...1000))
}
Text($document)
}
.navigationTitle("SimpleText")
}
}
}
@propertyWrapper struct Document: DynamicProperty {
@State private var value = ""
init() {
_value = State(wrappedValue: "")
}
var wrappedValue: String {
get {
value
}
nonmutating set {
value = newValue
}
}
var projectedValue: String {
return "ok - " + wrappedValue
}
}