apple/SwiftUI & Combine
SwiftUI DynamicProperty
lgvv
2024. 8. 14. 22:18
SwiftUI DynamicProperty
뷰의 외부 속성을 업데이트하는 저장 프로퍼티에대한 인터페이스
view의 body를 다시 계산(recomputing)하기 전에 해당 속성값을 제공
- 내부적으로 update() 메소드에 의해 기본 값을 업데이트.
- 이 메소드는 필수이며 기본 구현이 제공됨. 이를 통해 저장 프로퍼티를 새로운 값으로 갱신.
- 일반적으로 SwiftUI에서 @State와 같은 프로퍼티 래퍼가 사용될 때 뷰의 상태가 변하면 자동으로 호출되어 뷰의 상태를 최신으로 유지하는데 사용.
예제
내용을 FileManager에 실시간으로 저장하는 예제.
@AppStroage와 동일한 기능.
@propertyWrapper
struct Document: DynamicProperty {
@State private var value = ""
private let url: URL
var wrappedValue: String {
get { value }
nonmutating set {
do {
try newValue.write(to: url,
atomically: true,
encoding: .utf8)
value = newValue
} catch {
print("파일 작성 실패")
}
}
}
var projectedValue: Binding<String> {
Binding(
get: { wrappedValue },
set: { wrappedValue = $0 }
)
}
init(_ filename: String) {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
url = paths[0].appendingPathComponent(filename)
let initialText = (try? String(contentsOf: url)) ?? ""
_value = State(wrappedValue: initialText)
}
}
struct DocumentView: View {
@Document("chat") var document
var body: some View {
VStack {
Text(document)
Spacer()
TextField("저장할 내용 입력", text: $document)
.padding(20)
.background(.blue.opacity(0.2))
}
}
}
#Preview {
DocumentView()
}
@propertyWrapper를 사용하여 wrappedValue를 구현
projectedValue에 Binding을 통해 get - set을 사용하여 데이터 동적으로 처리되도록 반영
- nonmutating set으로 해야하는 이유
1. projectedValue가 struct 내부에 value를 변경하지 못함.
2. nonmutating으로 처리하여 구조체를 냅둔 채 @State로 선언된 value를 변화시킴.
nonmutating의 경우에는 아래 개념 참고.
(참고)
https://developer.apple.com/documentation/swiftui/dynamicproperty