[Swift/SwiftUI]subscript를 사용하여 편하게 바인딩
정황
너는 다음과 같은 것이 있다
enum
.Binding<検索条件>
를 수락한 후 이 검색 조건SearchView
을 설정합니다.enum 検索条件 {
case 完全一致(String)
case 前方一致(String)
case 部分一致(String)
enum タイプ {
case 完全一致, 前方一致, 部分一致
var ジェネレータ: (String) -> 検索条件 {
switch self{
case .完全一致: return 検索条件.完全一致
case .前方一致: return 検索条件.前方一致
case .部分一致: return 検索条件.部分一致
}
}
}
}
간단하게 실시해 봅시다.struct SearchView1: View {
@Binding var 条件: 検索条件
@State var タイプ: 検索条件.タイプ = .部分一致
@State var 中身 = ""
var body: some View {
VStack{
Picker("タイプを設定", selection: $タイプ){
Text("完全一致").tag(検索条件.タイプ.完全一致)
Text("前方一致").tag(検索条件.タイプ.前方一致)
Text("部分一致").tag(検索条件.タイプ.部分一致)
}
TextField("中身", text: $中身)
}
.onChange(of: タイプ){ value in
self.update()
}
.onChange(of: 中身){ value in
self.update()
}
}
func update(){
条件 = タイプ.ジェネレータ(中身)
}
}
언뜻 보면 좋은데 자세히 보면 신경 쓰이는 부분이 있어요.onChange
를 먼저 정의했지만 미묘했다.처리는 같지만 두 가지 불쾌함을 써야 한다.View
의 외측 변경条件
시에는 검출할 수 없습니다.따라서 외부에 기반한 변경クエリ
과 タイプ
은 변경할 수 없으며 상황에 따라 상태가 편차가 발생할 수 있다.고장이 뚜렷하다.subscript로 해결
그곳
subscript
에서 활약하고 있다.우선 다음extension
에서 두 개subscript
를 정의한다.extension 検索条件 {
enum タイプキー {case タイプ}
subscript(_ key: タイプキー) -> タイプ {
get {
switch self {
case .完全一致: return .完全一致
case .前方一致: return .前方一致
case .部分一致: return .部分一致
}
}
set {
let 中身 = self[.中身]
self = newValue.ジェネレータ(中身)
}
}
enum 中身キー {case 中身}
subscript(_ key: 中身キー) -> String {
get {
switch self {
case let .完全一致(value), let .前方一致(value), let .部分一致(value):
return value
}
}
set {
let タイプ = self[.タイプ]
self = タイプ.ジェネレータ(newValue)
}
}
}
이 기능을 가져오면 다음과 같이 쓸 수 있습니다SearchView
.struct SearchView2: View {
@Binding var 条件: 検索条件
var body: some View {
VStack{
Picker("タイプを設定", selection: $条件[.タイプ]){
Text("完全一致").tag(検索条件.タイプ.完全一致)
Text("前方一致").tag(検索条件.タイプ.前方一致)
Text("部分一致").tag(検索条件.タイプ.部分一致)
}
TextField("中身", text: $条件[.中身])
}
}
}
는 내부 여분의 변수가 아니라 직접 귀속条件
에서 얻은 값이기 때문에 외부条件
에서 변경이 발생하더라도 상태에 편차가 생기지 않는다.또 onChange
도 사라지고 본질적인 부분만 남았다.시용용
View
도 준비했다.struct SearchViewTest: View {
@State private var 条件1: 検索条件 = .部分一致("")
@State private var 条件2: 検索条件 = .部分一致("")
var body: some View {
SearchView1(条件: $条件1)
Text(verbatim: "\(条件1)").font(.caption)
Button("リセット"){
//SearchViewの外部から条件を変更してみる
条件1 = .部分一致("")
}
.font(.caption)
SearchView2(条件: $条件2)
Text(verbatim: "\(条件2)").font(.caption)
Button("リセット"){
//SearchViewの外部から条件を変更してみる
条件2 = .部分一致("")
}
.font(.caption)
}
}
작업 정보
extension
부분의 보충 설명.우선
extension
에 추가된 subscript
정의에서 내부 정의enum
를 매개 변수로 한다.이렇게 하면 条件[.タイプ]
또는条件[.中身]
이라는 표기를 실현할 수 있다.enum タイプキー {case タイプ}
subscript(_ key: タイプキー) -> タイプ
enum 中身キー {case 中身}
subscript(_ key: 中身キー) -> String
또한Binding
형은 사용KeyPath
의dynamicMemberLookup
와 대응한다.이렇게 하면 $条件[dynamicMember: \.[.タイプ]]
를 $条件[.タイプ]
로 약기할 수 있다.또한 귀속
subscript
하면 수치는 그get
와 set
를 통해 달라진다.이것은 $array[0]
와 같은 귀속을 사용한 동작이다.별법
별도로 사용하지 않더라도
subscript
다음과 같은 정의를 할 수 있다.subscript
내의 처리는 각각 Binding
의get
와 set
매개 변수로 지정되어 거의 변화가 없다.동작도 SearchView2
와 똑같다.struct SearchView3: View {
@Binding var 条件: 検索条件
var タイプ: Binding<検索条件.タイプ> {
.init(
get: {
switch 条件 {
case .完全一致: return .完全一致
case .前方一致: return .前方一致
case .部分一致: return .部分一致
}
},
set: { newValue in
let 中身 = self.中身.wrappedValue
条件 = newValue.ジェネレータ(中身)
}
)
}
var 中身: Binding<String> {
.init(
get: {
switch 条件 {
case let .完全一致(value), let .前方一致(value), let .部分一致(value):
return value
}
},
set: { newValue in
let タイプ = self.タイプ.wrappedValue
条件 = タイプ.ジェネレータ(newValue)
}
)
}
var body: some View {
VStack{
Picker("タイプを設定", selection: タイプ){
Text("完全一致").tag(検索条件.タイプ.完全一致)
Text("前方一致").tag(検索条件.タイプ.前方一致)
Text("部分一致").tag(検索条件.タイプ.部分一致)
}
TextField("中身", text: 中身)
}
}
}
이 방법도 좋은 것 같지만 몇 가지 측면에서 subscript
하는 방법을 추천합니다.사용
subscript
의 경우 스위프트 UI에서 상징적으로 사용된$
기호를 유지할 수 있어 가독성이 높다.subscript
를 사용하는 경우 액세스 값 자체에 대해 쓰지 않아도 됩니다.wrappedValue
.subscript
를 압도적으로 유창하게 쓴다.subscript
방법을 사용하거나, 과부하를 위해 불필요한 매개 변수를 설정하는 등 다소 헛수고를 한 부분도 있는데, 항상 그런 압도적인 이점을 선택해야 한다는 것은 아니다.웃기다
(가공 인용) 단지 보기를 실현하기 위해 extension을 추가하는 것이 좋지 않습니까?
나는 만약 적절하게 방문 수식자를 주면 큰 문제가 되지 않을 것이라고 생각한다.코딩 규약 등을 염두에 두면
SearchView3
방식이 좋다.(허구 인용) 원래 이렇게 하면 편하겠죠?
struct 検索条件 {
var タイプ: タイプ
var 中身: String
enum タイプ {
case 完全一致, 前方一致, 部分一致
}
}
현실에서는 결코 그렇게 순조롭지 않다. 예를 들면 내용이 각기 다르다case 完全一致(完全一致データ)
case 前方一致(前方一致データ)
case 部分一致(部分一致データ)
와 같은 유형에 따라 각자text
속성을 가진 장면이 있다.데이터 형식의 변경으로 효과적인 장면에 대응하는 데는 한계가 있지만 이번 설명 방법은 일반적으로 사용된다.끝맺다
정의 부분은 좀 번거롭지만
subscript
를 사용하면 귀속을 스마트하게 쓸 수 있습니다.기분 좋네.
Reference
이 문제에 관하여([Swift/SwiftUI]subscript를 사용하여 편하게 바인딩), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/en3_hcl/articles/aef18575a96bec텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)