Ответ
@State и @Binding — это property wrappers для управления состоянием в декларативной парадигме SwiftUI, но они решают разные задачи: владение данными и их передача.
@State: Владение состоянием
- Назначение: Хранит приватное, внутреннее состояние конкретного View.
- Владение: Данные принадлежат и управляются этим View. SwiftUI создает и хранит значение.
- Область видимости: Изменяется и используется только внутри этого View (или его дочерних вью через
@Binding). - Жизненный цикл: SwiftUI уничтожает состояние, когда View удаляется.
- Инициализация: Значение устанавливается при создании View.
struct ToggleView: View {
// View ВЛАДЕЕТ этим булевым значением
@State private var isOn: Bool = false
var body: some View {
VStack {
// Локальное состояние можно изменять напрямую
Button("Переключить") {
isOn.toggle() // Изменение @State вызывает обновление View
}
// Для передачи дочернему вью используется $ для создания Binding
ChildView(isOn: $isOn)
}
}
}
@Binding: Ссылка на состояние
- Назначение: Создает двустороннюю связь (two-way binding) с состоянием, которым владеет другое (родительское) View.
- Владение: Не владеет данными, только читает и записывает значение из источника (например,
@Stateродителя). - Область видимости: Позволяет дочернему View изменять состояние родителя.
- Синтаксис: Получается через префикс
$перед свойством с@State(или другим источником данных).
struct ChildView: View {
// ChildView НЕ владеет данными, только имеет ссылку на них
@Binding var isOn: Bool
var body: some View {
Toggle("Опция", isOn: $isOn) // Toggle меняет значение в @State родителя
.padding()
}
}
Ключевая аналогия
@State— это как private переменная в классе.@Binding— это как inout параметр функции, который позволяет функции изменять значение внешней переменной.
Когда что использовать?
- Используйте
@Stateдля простых значений, принадлежащих этому View (флаги, текст поля ввода, значение слайдера). - Используйте
@Bindingкогда нужно:- Передать состояние из родительского View в дочернее для модификации.
- Создать общий контрол (кастомный Toggle, TextField), который должен работать с внешним состоянием.
- Избежать подъема состояния (state hoisting) на несколько уровней вниз, передавая
Binding.
Ответ 18+ 🔞
А, ну вот, опять эти ваши @State и @Binding! Слушай, давай разберёмся, а то у меня уже волнение ебать, как люди в них путаются, в рот меня чих-пых!
Представь себе, блядь, что твой View — это такая квартира. Так вот:
@State — это твой личный, ёбта, холодильник в этой квартире. Ты там хранишь свои пивко, колбаску. Ты им владеешь, ты его наполняешь, ты из него жрёшь. Данные — твои, приватные. Стоит он у тебя на кухне, и если ты съедешь с этой квартиры (View удалится), то холодильник, блядь, нахуй выкинут вместе с твоим полусъеденным салатом. Вот и весь жизненный цикл.
struct MyHumbleAbode: View {
// Это мой личный холодильник, блядь. Я тут храню, сколько у меня бутылок пива.
@State private var beerCount: Int = 10
var body: some View {
VStack {
// Я могу сам из него взять!
Button("Выпить пивка") {
if beerCount > 0 { beerCount -= 1 } // Один глоток — и обновление интерфейса, красота!
}
// А могу дать доступ к нему соседу (дочернему виду), но через специальную ссылку!
NeighborView(beerInMyFridge: $beerCount)
}
}
}
А теперь @Binding — это, сука, дубликат ключа от этого твоего холодильника! Ты даёшь этот ключ соседу (NeighborView). Сосед не владеет холодильником, овердохуища пива ему не купить — но он может прийти, открыть и взять твоё пиво! Или, что ещё хуже, подкинуть туда селёдку. Двусторонняя связь, ёпта! Он меняет — у тебя в основном холодильнике тоже меняется.
struct NeighborView: View {
// У меня нет своего пива. Но есть ключ от твоего холодильника!
@Binding var beerInMyFridge: Int
var body: some View {
HStack {
Text("Пива в твоём холодильнике: (beerInMyFridge)")
// И я, такой довольный, могу его опустошить!
Button("Сосед выпил") {
beerInMyFridge -= 1 // Ёбта, это же меняет значение в @State родителя!
}
}
.padding()
}
}
Ключевая мысль, блядь, запомни:
@State — это владение (холодильник твой).
@Binding — это ссылка, доступ (ключ от чужого холодильника).
Когда что юзать, бля?
@State— для всего мелкого и локального внутри одного экрана. Флажок включён/выключен, текст в поле, позиция слайдера. Всё, что живёт и умирает вместе с этим экраном.@Binding— когда надо, блядь, дать возможность детям или кастомным компонентам менять состояние родителя. Кастомная кнопка, общий переключатель, поле ввода — всё, что должно пробрасывать изменения наверх.
Вот и вся философия. Не усложняй, а то сам от себя охуеешь. Главное — не давай @Binding первому встречному, а то останешься без пива и с селёдкой в холодильнике. Всё, вопрос закрыт.