Перечисление SwiftUI @State остается нулевым даже после присвоения значения

#ios #swift #swiftui

#iOS #swift #swiftui

Вопрос:

Xcode 12 iOS 14 beta 8

У меня есть представление SwiftUI, которое может представлять три разных листа в зависимости от состояния приложения. Вместо трех отдельных.модификаторы листа и три разных @State свойства для обработки этих листов, я подумал, что использование перечисления для определения того, какой лист представить, было бы элегантным решением…но это не работает.

Вот перечисление:

 enum SheetType: Int, Identifiable {
    case welcome
    case notification
    case assignment

    var id: Int { rawValue }
}
  

SheetType должно соответствовать идентификатору из-за .sheet(item:content:) модификатора в представлении:

 struct MainTabView: View {
    @State var sheetType: SheetType?

    var body: some View {
        Text("Hello World!")
        .onAppear(perform: checkForSheet)
        .sheet(item: $sheetType) { _ in
            sheetView
        }
    }
}
  

При MainTabView появлении checkForSheet ищет условия, которые гарантировали бы представление определенного листа, и, если какие-либо совпадают, устанавливает sheetType свойство следующим образом: sheetType = .welcome . Затем следует вызвать sheetView , который возвращает соответствующий лист.

Проблема в том, что независимо от того, где в коде я обновляю значение sheetType , оно остается нулевым. Я вижу изменение значения на долю секунды в отладчике, но затем оно переключается обратно на ноль, прежде чем может быть представлен лист. Я в полной растерянности. Есть ли что-то очевидное, чего мне не хватает, или это просто еще одна ошибка?


РЕДАКТИРОВАТЬ 1:

Благодаря коду Asperi я смог представить лист, но проблема в том, что sheetView свойство, которое возвращает правильный лист, также не работает. Вместо этого я изменил его на функцию и изменил .sheet модификатор:

 .sheet(item: $sheetType) { type in
    createSheetView(of: type)
}

  

Вот код для createSheetView(of:) . Я подтвердил в отладчике, что значение sheetType равно .welcome , но оператор switch по-прежнему возвращает значение по умолчанию, которое бесполезно EmptyView .

 
func createSheetView(of type: SheetType) -> some View {
    switch sheetType {
    case .welcome: return AnyView(WelcomeSplashView())
    case .notification: return AnyView(NotificationPermissionView(notificationAccessWasGranted: .constant(false)))
    default:
        return AnyView(EmptyView())
    }
}

  

РЕДАКТИРОВАТЬ 2:

Я идиот. Я забыл изменить оператор switch с switch sheetType (который является @State свойством представления) на новый switch type (который принимает параметр функции). Теперь это работает 🙂

Ответ №1:

Вот некоторый реплицированный код, который работает с Xcode 12b5

ДЕМОНСТРАЦИЯ

 enum SheetType: Int, Identifiable {
    case welcome
    case notification
    case assignment

    var id: Int { rawValue }
}

struct MainTabView: View {
    @State var sheetType: SheetType?

    var body: some View {
        Text("Hello World!")
        .onAppear(perform: checkForSheet)
        .sheet(item: $sheetType) { _ in
            Text("sheetView")
        }
    }

    func checkForSheet() {
        sheetType = .welcome   // << make sure to update always in main queue
    }
}
  

Комментарии:

1. Хм… Я поиграл с этим кодом, и похоже, что причиной проблемы является наличие условного представления внутри листа. Спасибо, что указали мне правильное направление!

2. Я добавил еще немного кода к своему исходному сообщению, если у вас есть время взглянуть еще раз. Спасибо!