Что делает ключевое слово SwiftUI `@State`?
Учебник SwiftUI использует @State
ключевое слово для обозначения изменчивого состояния пользовательского интерфейса:
@State var showFavoritesOnly = false
Он предлагает это резюме:
Состояние - это значение или набор значений, которые могут изменяться с течением времени и влиять на поведение, содержимое или макет представления. Вы используете свойство с атрибутом @State для добавления состояния в представление.
- Что именно означает ключевое слово?
- Как мутирует
@State
переменная вызывает пересчет представления? - Как другие переменные неизменяемы в
body
добытчик?
7 ответов
@State
ключевое слово @propertyWrapper
, функция, недавно представленная в Swift 5.1. Как объясняется в соответствующем предложении, это своего рода оболочка значения, избегающая стандартного кода.
Примечание: @propertyWrapper
ранее назывался @propertyDelegate
, но это изменилось с тех пор. Смотрите этот пост для получения дополнительной информации.
Официальная документация @State содержит следующее:
SwiftUI
управляет хранением любого имущества, которое вы объявляете государством. Когда значение состояния изменяется, представление делает его недействительным и пересчитывает тело. Используйте государство как единственный источник правды для данного взгляда.Экземпляр State не является самим значением; это средство чтения и изменения значения. Чтобы получить доступ к базовому значению состояния, используйте его свойство value.
Поэтому, когда вы инициализируете свойство, которое помечено @State
вы на самом деле не создаете свою собственную переменную, а скорее подсказываете SwiftUI
создать "что-то" в фоновом режиме, которое хранит то, что вы установили, и контролирует это отныне! Твой @State var
просто действует как делегат для доступа к этой оболочке.
Каждый раз, когда ваш @State
переменная написана, SwiftUI
будет знать, как он отслеживает это. Он также будет знать, является ли @State
переменная была прочитана из View
"s body
, Используя эту информацию, он сможет пересчитать любой View
сославшись на @State
переменная в своем body
после изменения этой переменной.
Позвольте мне добавить кое-что еще, если вы знаете React Native.
@State
собственность очень похожа на this.state
объект в React Native.
Например:
struct Foobar: some View {
@State var username = ""
}
class Foobar extends React.Component {
constructor(props) {
super(props);
this.state = {
username: '',
};
}
}
Когда вы изменяете переменную username, они будут иметь тот же эффект, что и рендеринг текущей страницы.
Это хорошо объяснено на примере из видео WWDC - сессия 204 (начинается в 16:00, цитата начинается в 20:15)
Одно из особых свойств
@State
Переменные - это то, что SwiftUI может наблюдать, когда они читаются и пишутся. Потому что SwiftUI знает, чтоzoomed
был прочитан вbody
, он знает, что рендеринг представления зависит от этого. Что означает - когда переменная изменяет структуру, будет запрашиватьсяbody
снова используя новый@State
стоимость.
@State
как обертка свойств также разработана и обоснована в потоке данных через Swift UI (5:38) WWDC vid. Показано, как это решает проблему, когда нам нужно непостоянное значение в неизменяемом (struct
) View
,
Мне нравится, как это объясняет профессор Пол Хегарти из Стэнфорда. Он сказал, что @State в основном преобразует эту переменную в указатель на какое-то логическое значение где-то еще в памяти, и там изменяется значение. Но ваша переменная - теперь указатель с @State- не изменяется, всегда указывает на это место в памяти.
Если вы нажмете в @State
Вы можете видеть, что у него есть несколько добытчиков. Один с Value
другой с Binding<Value>
, SwiftUI, кажется, сильно зависит от реактивного программирования (и их новых Combine
Framework, и поскольку мы не можем увидеть полную реализацию этих оболочек, я ожидаю, что значения, которые хранятся через @State
Обертки свойств управляются CurrentValueSubject
из Combine
, Как следует из названия, это, по сути, хранит текущее значение, которое затем может быть использовано как связываемое свойство с помощью $
синтаксис.
Примечание. Принятый ответ правильный, но если вы пытаетесь найти более простое объяснение, которое я пробовал ниже.
Обертка свойства @State позволяет нам изменять значения внутри структуры.
Примечание . - Вы не можете изменить свойство в структуре, так как это типы значений, поэтому это не разрешено.
struct ExampleTextView: View {
// Declare a variable with state property wrapper
@State private var shouldChangeText: Bool = false
var body: some View {
Text("Just an example")
.foregroundColor(Color.white)
}
}
Если вы задаетесь вопросом, должны ли мы добавить спецификатор частного доступа?
Да, как правило, Apple рекомендует, чтобы свойство @State не использовалось совместно с другими представлениями, поскольку для этого @ObservedObject и @EnvironmentObject существуют более конкретные оболочки свойств.
Но если это тип значения, как его можно изменить, где он хранится?
Поэтому всякий раз, когда мы помечаем свойство с помощью @State, мы перемещаем его хранилище из структуры в общее хранилище, управляемое SwiftUI.
Если вы думаете, что если вы сравниваете со Swift, там это делается так,
struct Example {
var exampleType: String
mutating func changeType() {
exampleType = "Are we allowed to do this?"
}
}
Кредит: обратите внимание, что этот ответ вдохновлен этим сообщением https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-state-property-wrapper .
Если вы знаете о разработке на C# и Windows. @State
похоже, если не то же самое, что x:Bind
или Binding
.. По коллекции похоже, если не так, как ObservableCollection
.
Как сказал Фредпи, SwiftUI содержит список обновлений для vars с @State
делегат собственности.