skip to Main Content

I want to perform some actions when any property value gets changed in the model.

struct RoomDataModel: Equatable{
    
    var selectedLocationName : String = ""
    var selectedRoomName : String = ""
    var selectedRoomImage : String = ""
    var roomId: String = ""
    
    static func == (lhs: RoomDataModel, rhs: RoomDataModel) -> Bool {
        return lhs.selectedRoomName == rhs.selectedRoomName && lhs.selectedRoomImage == rhs.selectedRoomImage
    }
    
}

How I used room object in View :

 @State var roomDetail = RoomDataModel()

 var body: some View {
    someview
    .onChange(of: roomDetail) { newValue in
         //performing some action here
    }
}

I have the above model which triggers onChange() when selectedRoomName and selectedRoomImage both values changed. but I want to trigger onChange even if there is a change in any one of the property values. If I change only selectedRoomImage then onChange() is not getting triggered.

I am new to SwiftUI and Equatable protocol. I would greatly appreciate any help.
Thanks.

2

Answers


  1. The onChange method is not being triggered when only selectedRoomImage is changed because the Equatable protocol’s == function is only checking for equality between the selectedRoomName and selectedRoomImage properties of the two instances being compared.

    To trigger the onChange method when any one of the property values changes, you can modify the == function to check for equality between all the properties of the two instances being compared. Here’s an example:

    static func == (lhs: RoomDataModel, rhs: RoomDataModel) -> Bool {
        return lhs.selectedLocationName == rhs.selectedLocationName &&
               lhs.selectedRoomName == rhs.selectedRoomName &&
               lhs.selectedRoomImage == rhs.selectedRoomImage &&
               lhs.roomId == rhs.roomId
    }
    
    Login or Signup to reply.
  2. Try this approach, removing the static func == ... from RoomDataModel.

    Here is the example code that shows it works:

    struct ContentView: View {
        @State var roomDetail = RoomDataModel()
        
        var body: some View {
            SomeView(roomDetail: $roomDetail)
                .onChange(of: roomDetail) { newValue in
                    print("----> roomDetail: (roomDetail)") // <-- this will be done on every change
                }
        }
    }
    
    struct RoomDataModel: Equatable {
        var selectedLocationName : String = ""
        var selectedRoomName : String = ""
        var selectedRoomImage : String = ""
        var roomId: String = ""
    }
    
    struct SomeView: View {
        @Binding var roomDetail: RoomDataModel // <-- here ensure it is @Binding
        
        var body: some View {
            // --- here make any change you like
            VStack {
                TextField("type selectedLocationName", text: $roomDetail.selectedLocationName).border(.red)
                TextField("type selectedRoomName", text: $roomDetail.selectedRoomName).border(.red)
                TextField("type selectedRoomImage", text: $roomDetail.selectedRoomImage).border(.red)
                TextField("type roomId", text: $roomDetail.roomId).border(.red)
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search