#ios #swift #swiftui
#iOS #swift #swiftui
Вопрос:
Я пытаюсь использовать переменную глобальной среды в качестве статуса, чтобы проверить, должно ли приложение отображать экран загрузки (блокировка пользовательского интерфейса и предотвращение касаний)
Я не использую @EnvironmentObject
, потому что у меня может быть несколько объектов для разных уведомлений
Ниже приведен код, который я использую. Согласно каждому материалу, который я нашел в Интернете, он должен работать, и представление должно обновляться с правильным кодом. И все же мое приложение не меняется
import SwiftUI
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
NewView()
.environment(.counter, GlobalCounter(start: 5))
}
}
}
struct NewView: View {
@Environment(.counter) var counter: GlobalCounter
var body: some View {
Text("COUNT: (counter.value)")
Button("UP") {
counter.increment()
}
}
}
struct GlobalCounterKey: EnvironmentKey {
static public let defaultValue: GlobalCounter = GlobalCounter(start: 1)
}
extension EnvironmentValues {
var counter: GlobalCounter {
get {
return self[GlobalCounterKey.self]
}
set {
self[GlobalCounterKey.self] = newValue
}
}
}
class GlobalCounter: ObservableObject {
@Published var value: Int = 0
init(start: Int = 0) {
self.value = start
}
func increment() {
value = 1
}
}
Я использую базовый счетчик для целей тестирования, но он должен работать с перечислениями, строками и т. Д.
Что я делаю не так?
Комментарии:
1. Среда здесь не является подходящим инструментом — она не наблюдает за наблюдаемыми объектами. Вам необходимо ввести свой счетчик как ObservedObject.
2. Хорошо, тогда как я могу сделать его наблюдаемым? Мне нужно передать эту переменную нескольким дочерним представлениям. И диспетчер данных обновит его асинхронным методом. Как я могу заставить его обновлять представления?
3. @Asperi это неверно, согласно документации : «Если значение изменяется, SwiftUI обновляет любые части вашего представления, которые зависят от значения». Вы не можете напрямую изменять его значения, но вы можете вызывать методы изменения, которые, в моем случае, не запускают просмотры для обновления
4. Да, документация верна, но ваш GlobalCounter не является значением, это ссылка, и она не изменяется, измененное свойство ссылается где-то в памяти, но оно никак не связано со значением среды.
5. функция func increment() не является мутирующим методом. Если вы измените GlobalCounter на struct и добавите к нему «mutating», это так.
Ответ №1:
Используйте EnvironmentObject
вместо этого.
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(GlobalCounter(start: 5))
}
}
}
struct ContentView: View {
var body: some View {
NavigationView {
NewView()
}
}
}
struct NewView: View {
@EnvironmentObject var counter: GlobalCounter
var body: some View {
VStack{
Text("COUNT: (counter.value)")
Button("UP") {
counter.increment()
}
}
}
}
struct GlobalCounterKey: EnvironmentKey {
static public let defaultValue: GlobalCounter = GlobalCounter(start: 1)
}
extension EnvironmentValues {
var counter: GlobalCounter {
get {
return self[GlobalCounterKey.self]
}
set {
self[GlobalCounterKey.self] = newValue
}
}
}
class GlobalCounter: ObservableObject {
@Published var value: Int = 0
init(start: Int = 0) {
self.value = start
}
func increment() {
value = 1
}
}
Комментарии:
1. Как я уже говорил в вопросе, я стараюсь избегать
EnvironmentObject
, потому что хочу использовать несколько объектов. И использованиеenvironment(_:_:)
было бы лучшим для нас, потому что мы можем сказать, какая переменная получит какую переменную2. @NicosKaralis Можете ли вы дать больше информации в своем вопросе? Вы можете установить новый EnvironmentObject для дочерних элементов, если хотите использовать разные объекты, поэтому мне трудно понять, зачем вам EnvironmentValue