Home > AI > IOS > SwiftUI >

DynamicProperty

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

Leave a Reply