@Binding је Property Wrapper у SwiftUI који ствара референцу на податке које поседује друга компонента. Binding не чува вредност самостално — он само пружа приступ постојећем извору истине кроз пројекцију $. Према Apple Developer Documentation (2025), Binding обезбеђује реактивну двосмерну везу између родитељског и детет приказа без директног власништва над подацима. @Binding је кључни механизам за пренос променљивог стања низ хијерархију.
Главно
@Binding је Property Wrapper који ствара двосмерну везу између особине ускладиштене у родитељском приказу и детет компоненте. Главна разлика Binding у односу на @State: Binding не поседује податке. Он само чита и уписује вредност кроз прави извор — @State, @StateObject или други Binding у родитељу. Без Binding, детет прикази не би могли да мењају стање претка без колбекова или делегата.
Binding је имплементиран као структура са две особине: wrappedValue (тренутна вредност) и projectedValue (сам Binding, доступан кроз $). Када детет приказ промени wrappedValue кроз Binding, SwiftUI преноси промену у извор података и прецртава све зависне приказе. Ово се дешава синхроно у оквиру тренутног циклуса ажурирања.
Важна особина: @Binding није ограничен на једнослојни пренос. Binding се може преносити кроз више нивоа хијерархије — свака детет компонента добија референцу на исти извор података. Промена на било ком нивоу изазива јединствено ажурирање свих повезаних приказа.
Механизам двосмерне везе кроз @Binding се заснива на пројекцији Property Wrapperа. Када родитељ декларише @State var value: T, SwiftUI аутоматски генерише пројекцију $value типа Binding
struct SliderContainer: View {
@State private var value: Double = 0.5
var body: some View {
VStack {
Text("Вредност: \(value)")
SliderView(value: $value)
}
}
}
struct SliderView: View {
@Binding var value: Double
var body: some View {
Slider(value: $value, in: 0...1)
}
}
У примеру SliderContainer поседује @State value, а SliderView добија Binding кроз $value. Slider унутар SliderView је повезан са овим Bindingом. При превлачењу клизача, Slider мења вредност кроз Binding, што аутоматски ажурира @State у SliderContainer и оба приказа приказују тренутни број. Цео ланац ради без иједног колбека или обавештења.
За креирање Binding из @StateObject или @ObservedObject користи се иста пројекција: $object.property даје Binding
Пре SwiftUI стандардни начин преноса промена навише кроз хијерархију били су колбекови и делегати: родитељ је преносио затворење, детет компонента га је позивала при промени. @Binding нуди алтернативу са мање кода и декларативнијом синтаксом. Уместо преноса затворења за комплетирање, довољно је пренети $stateValue.
| Критеријум | @Binding | Колбекови |
|---|---|---|
| Код | Једна анотација + $ | Затворење + позив |
| Вишеслојност | Аутоматска | Ланац затворења |
| Тестирање | Binding(value:constant) | Mock-затворења |
| Читљивост | Висока | Средња |
| Флексибилност | Само подаци | Било која логика |
Користите @Binding када детет приказу треба само да чита и мења вредност. Ако су потребне споредне радње при промени (валидација, логирање, мрежни захтев), комбинујте Binding са колбеком: преносите Binding за податке и затворење за догађаје. На пример, TextField се може повезати са Bindingом, а onChange ће покренути валидацију.
@Binding се примењује у неколико типичних сценарија. Први — прилагођени контроли: прекидачи, клизачи, бирачи боја и други интерактивни елементи примају Binding за двосмерну синхронизацију. Други — модални прозори: застава приказа sheet се преноси као Binding, омогућавајући детет приказу да се затвори кроз presentationMode или директно подешавање.
Трећи образац — формулари са поделом. Ако се формулар састоји од више поља, свако поље се може издвојити у посебну компоненту која прима Binding за своју вредност. Ово поједностављује тестирање и поновну употребу поља између различитих формулара. Родитељска компонента остаје једини власник целог модела формулара.
struct FormField: View {
let title: String
@Binding var text: String
var body: some View {
VStack(alignment: .leading) {
Text(title).font(.caption)
TextField("Enter \(title.lowercased())", text: $text)
.textFieldStyle(.roundedBorder)
}
}
}
Компонента FormField прима наслов и Binding на стринг. Она приказује натпис и TextField повезан са прослеђеним Bindingом. Било који формулар може користити FormField више пута, преносећи $property за свако поље. Ово смањује дуплирање ознака и централизује стилизацију текстуалних поља.
SwiftUI омогућава ручно креирање Binding кроз иницијализатор Binding(get:set:). Ово је корисно када треба додати логику при читању или упису вредности. На пример, можете креирати Binding који форматира број пре чувања, или Binding који синхронизује вредност са удаљеним сервером при свакој промени.
struct ValidatedField: View {
@State private var email: String = ""
var emailBinding: Binding<String> {
.init(
get: { email },
set: { email = $0.lowercased().trimmingCharacters(in: .whitespaces) }
)
}
var body: some View {
TextField("Email", text: emailBinding)
}
}
У листингу, прилагођени emailBinding аутоматски претвара текст у мала слова и уклања размаке при свакој промени. TextField користи овај Binding уместо директног повезивања на $email. Такав приступ омогућава централизацију валидације и трансформације података унутар Bindinga, без затрпавања кода onChange руковаоцима.
Прва и најчешћа грешка — пренос вредности уместо Bindinga. Ако детет компонента декларише @Binding var text: String, а родитељ преноси text (без $), компајлер ће пријавити грешку: Cannot convert value of type 'String' to expected argument type 'Binding
Друга грешка — Binding на read-only податке. Ако детет приказу треба само да чита вредност, не користите @Binding — довољно је обично let или @State из родитеља. Binding подразумева могућност уписа, а додатна права измене отежавају отклањање грешака и нарушавају принцип минималних привилегија.
Трећи проблем — Binding.constant у продукцији. Binding.constant(value) ствара фиктивно повезивање без повратне спреге — измене се игноришу. Користите constant само за прототиповање и прегледе (Xcode Previews), али никад у стварном коду. За тестове користите Binding(get:set:) са контролисаним понашањем.
Често постављана питања
@State поседује податке и управља њиховим складиштењем на хеапу. @Binding само упућује на постојеће стање без власништва. @State је увек private, @Binding — улазни параметар детет приказа.
Да, кроз иницијализатор Binding(get:set:) или Binding.constant(value). Такође, Binding се може добити из @StateObject кроз пројекцију $object.$property и из Publisher кроз Binding(get:set:) унутар Subscribe.
@Binding се преноси ланчано: свака посредна компонента декларише @Binding и преноси га даље кроз $. Сви нивои упућују на један извор података у кореном приказу.
Binding.constant ствара нем омотач — сеттер игнорише нове вредности. Намењен је само за прототиповање и SwiftUI Previews, где повратна спрега од детет компоненте није потребна.
Да, Binding<T?> је подржан. Ако проследите Binding<String?>, детет приказ може поставити nil. Ово је згодно за опциона поља формулара или стања са могућношћу ресетовања.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође