I have a list of matches and when I type in the filter (TextField) it works fine. I also have a list of players the user can pick from. When they choose a player the func playerFilterChanged is called and usernameSearch is updated from the viewModel. I put a breakpoint on matches.nsPredicate = ... in the TextField onChange event and it is hit but the list doesn't update. Am I binding something incorrectly?
struct MatchHistory: View {
@EnvironmentObject private var viewModel: ViewModel
@Environment(\.managedObjectContext) var managedObjectContext
@Environment(\.dismiss) var dismiss
@FetchRequest(sortDescriptors: [NSSortDescriptor(key: "datetime", ascending: false)], animation: .default)
private var matches: FetchedResults<Match>
@Binding var showMatchHistory : Bool
@Binding var showChangePlayer : Bool
var cellPadding : CGFloat = 5
var deviceType = UIDevice.current.userInterfaceIdiom
@State private var orientation = UIDeviceOrientation.unknown
@State var showLoadingMessage : Bool = true
@State private var usernameSearch = ""
func playerFilterChanged(){
usernameSearch = viewModel.filterPlayerName
showChangePlayer = false
}
var body: some View {
GeometryReader{ geometry in
if(showLoadingMessage){
VStack{
Spacer()
HStack{
Spacer()
Text("Loading...").font(.largeTitle)
Spacer()
}
Spacer()
}
} else {
Form{
Section(header: Text("Filter by Player")){
HStack{
Text("Player Name")
HStack{
TextField("", text: $usernameSearch).disabled(false)
.onChange(of: usernameSearch){
newValue in
if(newValue.isEmpty == false){
let p0 = NSPredicate(format: "player1Record.playerName CONTAINS[cd] %@", newValue)
let p1 = NSPredicate(format: "player2Record.playerName CONTAINS[cd] %@", newValue)
matches.nsPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: [p0, p1])
}
}
Button("Clear Filter"){
viewModel.filterPlayerName = ""
usernameSearch = ""
}
Spacer()
Button("Filter by Player"){
showChangePlayer = true
}.sheet(isPresented: $showChangePlayer, onDismiss: playerFilterChanged){
FilterPlayer()
}
}.buttonStyle(BorderlessButtonStyle())
.padding(10).background(Color.darkGray).cornerRadius(16)
}
}
List {
ForEach(matches) { Match in
Section(header: Text(FormatDate(datetime: Match.datetime))){
VStack(alignment: .leading){
HStack{
Group{
Text("Player Name").frame(width: geometry.size.width * 0.3, alignment:.center).padding(cellPadding)
Text("1").frame(minWidth: 0, maxWidth: .infinity).padding(cellPadding)
Text("2").frame(minWidth: 0, maxWidth: .infinity).padding(cellPadding)
Text("3").frame(minWidth: 0, maxWidth: .infinity).padding(cellPadding)
Text("4").frame(minWidth: 0, maxWidth: .infinity).padding(cellPadding)
Text("5").frame(minWidth: 0, maxWidth: .infinity).padding(cellPadding)
if(Match.boardType == "N"){
Text("Total").frame(width: 50).padding(cellPadding)
}
}
if(Match.boardType == "W"){
Group{
Text("6").frame(minWidth: 0, maxWidth: .infinity).padding(cellPadding)
Text("7").frame(minWidth: 0, maxWidth: .infinity).padding(cellPadding)
Text("8").frame(minWidth: 0, maxWidth: .infinity).padding(cellPadding)
Text("9").frame(minWidth: 0, maxWidth: .infinity).padding(cellPadding)
Text("10").frame(minWidth: 0, maxWidth: .infinity).padding(cellPadding)
Text("Total").frame(width: 50).padding(cellPadding)
}
}
}.background(Match.boardType == "W" ? Color.blue : Color.darkGreen).cornerRadius(16)
MatchHistoryScoreRow(geometry: geometry, Match: Match, player: "player1", cellPadding: cellPadding)
if(Match.gameType != "singlePlayer"){
MatchHistoryScoreRow(geometry: geometry, Match: Match, player: "player2", cellPadding: cellPadding)
}
}
}.padding(.top, 10)
}
}
}
}
}
}
}
}