Оператор переключения не реагирует на изменения

#swiftui

Вопрос:

Я получил следующее заявление о переключении:

 @State private var selectedTestament = Testament.all
    
enum Testament: String, CaseIterable, Identifiable {
    case all
    case vt
    case nt
    var id: String { self.rawValue }
}
   
let filter: Testament
var filteredTestament: [Book] {
        
    switch filter {
    case .all:
        print("all")
        return bookViewModel.books
    case .nt:
        print("nt")
        return bookViewModel.books.filter { $0.testament == "NT" }
    case .vt:
        print("vt")
        return bookViewModel.books.filter { $0.testament == "VT" }
    }
}
 

И следующий сборщик

 Picker("Testament", selection: $selectedTestament) {
    Text("Both").tag(Testament.all)
    Text("VT").tag(Testament.vt)
    Text("NT").tag(Testament.nt)
}
.pickerStyle(SegmentedPickerStyle())
Text(
 

Независимо от того, нажимаю ли я «Оба», «VT» или «NT», я вижу только сообщение от print("all") , напечатанное в консоли.
Text("Testament: (selectedTestament.rawValue)") с другой стороны, обновление выполняется правильно и отображается правильный текст, но почему на консоль выводится только «все», а не «nt» / «vt» при переключении средства выбора?

filteredTestament используется здесь:

 ForEach(filteredTestament) { book in
  NavigationLink(
    destination: ChapterView(book: book),
    label: {
      HStack {
        VStack(alignment: .leading, spacing: 4) {  
          Text(book.name)
          Text(book.author)
          Text("(book.chapters) chapters")
        }
      }
    })
}
})
}
.onAppear {
  self.bookViewModel.fetchBooks()
}
 

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

1. Где ваш код, который вызывает filteredTestaments ? Спасибо

2. В списке ниже — но это пока не имеет значения — я не могу заставить оператор switch case работать. ForEach(filteredTestaments) {...}

3. Это не имеет значения. Ваше print утверждение находится внутри функции, которая не вызывается в отображаемом коде. 😀

4. На данный момент у вас есть привязка к selectedTestament . Затем у вас будет текст, который показывает selectedTestament , какое обновление выполняется правильно. Но в своем переключателе вы ничего не используете selectedTestament для включения. Ты употребляешь filter . Но filter нигде не обновляется в вашем коде. Можете ли вы показать код, который обновляет filter значение? Спасибо

5. Я обновил код, чтобы показать каждую часть

Ответ №1:

Я думаю, что вы добавили дополнительное свойство, фактически не нуждаясь в нем.

Ваш выбор обновляется selectedTestament , но ваш коммутатор использует filter то, что на самом деле никогда не обновляется.

Если вы удалите filter , вы должны быть в состоянии это сделать…

 @State private var selectedTestament = Testament.all

var filteredTestament: [Book] {
    switch selectedTestament {
    case .all:
        print("all")
        return bookViewModel.books
    case .nt:
        print("nt")
        return bookViewModel.books.filter { $0.testament == "NT" }
    case .vt:
        print("vt")
        return bookViewModel.books.filter { $0.testament == "VT" }
    }
}
 

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

1. Это действительно работает — спасибо. Зачем все filter портить? Я предположил, что мне нужна какая-то форма вычисляемого свойства

2. filter строго говоря, это не значит все испортить. Это просто не обновляется. У вас есть свойство, которое обновляется вашим picker , но затем вы игнорируете его и используете что-то другое для фильтрации массива. Вы Text обновлялись, потому что использовали selectedTestament свойство, и поэтому, когда средство выбора изменило его, оно получило новое значение. Вы просто добавили лишнее значение, которое не было связано с обновлениями сборщика. Но на самом деле… тебе просто это было совсем не нужно. 😀