ios – The right way to stop SwiftUI view to redraw each time on Printed property replace?

0
26
ios – The right way to stop SwiftUI view to redraw each time on Printed property replace?


I’ve a LandingView that has a viewModel which is an ObservableObject. LandingView masses some CardViews dynamically and passes a mannequin object (Binding property).

CardView additional nests 4 totally different subviews and passes the attributes wanted by Binding. There are textual content fields in these 4 subviews. When the consumer updates the textfield knowledge, the up to date knowledge travels again to viewModel by Binding.

Now the issue is that when the consumer keys in a single character in any of these textual content fields, the viewmodel is up to date and therefore the LandingView is re-drawn which ends up in the textual content area shedding focus and consumer has to faucet on the textual content area once more.

Is there a approach to repair this? I do know that I can repair it by eliminating the Binding properties and have another mechanism to take care of knowledge movement. However, can I repair it within the present setup itself?

Thanks a lot upfront!!!!

struct LandingView: View {
    @StateObject var viewModel = LandingViewModel(gridDataArray: [])
    @State var identify: String = ""
    
    var physique: some View {
        let _ = Self._printChanges()
        ZStack {
            Shade(pink: 242/255, inexperienced: 242/255, blue: 242/255)
            listView
               .background(Shade.white)
               .padding()
        }
        
    }
 
    
    non-public var listView: some View {
        ScrollView {
            VStack {
                ForEach(Array(viewModel.gridDataArray.enumerated()), id: .component) { index, component in
                    CardView(dataModel: $viewModel.gridDataArray[index])
                        .equatable()
                }
            }
        }
    }
}

struct CardView: View, Equatable {
    static func == (lhs: CardView, rhs: CardView) -> Bool {
        lhs.dataModel.hashValue == rhs.dataModel.hashValue
    }
    
    @Binding var dataModel: LandingViewDataModel
    
    var physique: some View {
        VStack(spacing: 0) {
            NavyBlueView(productName: $dataModel.productName, 
                         productId: $dataModel.productId,
                         productLabel: dataModel.productLabel)
            YellowView(weightedProductPrice: $dataModel.weightedProductPrice, 
                       wacSubWACUnitPrice: $dataModel.wacSubWACUnitPrice,
                       pvpUnitPrice: $dataModel.pvpUnitPrice)
            
            SkyBlueView(weightedPriceUsagePercent: $dataModel.weightedPriceUsagePercent,
                        wacSubWACUnitPricePercent: $dataModel.wacSubWACUnitPricePercent,
                        pvpUnitPricePercent: $dataModel.pvpUnitPricePercent,
                        totalPercent: $dataModel.totalPercent)
            GreenView(weightedPriceCalculated: $dataModel.weightedPriceCalculated,
                      wacSubWACUnitPriceCalculated: $dataModel.wacSubWACUnitPriceCalculated,
                      pvpUnitPriceCalculated: $dataModel.pvpUnitPriceCalculated,
                      totalCalculated: $dataModel.totalCalculated)
        }
    }
}

struct NavyBlueView: View {
    @Binding var productName: String
    @Binding var productId: String?
    var productLabel: String
    
    var physique: some View {
        VStack(alignment: .main) {
            Textual content(productLabel)
                .padding()
                .padding(.backside, -10)
                .foregroundStyle(Shade.white)
                .body(maxWidth: .infinity, alignment: .main)
            
            HStack {
                Spacer().body(width: 10)
                TextField("Product Identify", textual content: $productName)
                    .textFieldStyle(.plain)
                    .body(maxWidth: .infinity, maxHeight: .infinity)
            }
            .background(Rectangle().fill(Shade.white))
            .body(width: 500, peak: 35)
            .padding(.main, 15)
            .padding(.backside, 10)
            
            HStack {
                Textual content("      ")
                    .body(maxWidth: .infinity)
                Textual content("Weighted Value")
                    .body(maxWidth: .infinity)
                Textual content("WAC/SubWAC Unit Value")
                    .body(maxWidth: .infinity)
                Textual content("340B/PVP Unit Value")
                    .body(maxWidth: .infinity)
                Textual content("Complete")
                    .body(maxWidth: .infinity)
            }
            .foregroundStyle(Shade.white)
            .padding(.backside, 10)
        }
        .background(Shade(pink: 41 / 255, inexperienced: 78 / 255, blue: 124 / 255))
        .clipShape(.rect(
            topLeadingRadius: 10,
            bottomLeadingRadius: 0,
            bottomTrailingRadius: 0,
            topTrailingRadius: 10)
        )
        .padding(.horizontal)
    }
}

struct YellowView: View {
    @Binding var weightedProductPrice: String
    @Binding var wacSubWACUnitPrice: String
    @Binding var pvpUnitPrice: String
    var physique: some View {
        HStack {
            Group {
                Textual content("Product Value")
                
                HStack {
                    Spacer().body(width: 10)
                    TextField("Product worth", textual content: $weightedProductPrice)
                        .textFieldStyle(.plain)
                        .body(maxWidth: .infinity, maxHeight: .infinity)
                }
                .background(Rectangle().fill(Shade.white))
                .body(peak: 35)
                
                HStack {
                    Spacer().body(width: 10)
                    TextField("Product worth", textual content: $wacSubWACUnitPrice)
                        .textFieldStyle(.plain)
                        .body(maxWidth: .infinity, maxHeight: .infinity)
                }
                .background(Rectangle().fill(Shade.white))
                .body(peak: 35)
                .padding(10)
                
                HStack {
                    Spacer().body(width: 10)
                    TextField("Product worth", textual content: $pvpUnitPrice)
                        .textFieldStyle(.plain)
                        .body(maxWidth: .infinity, maxHeight: .infinity)
                }
                .background(Rectangle().fill(Shade.white))
                .body(peak: 35)
                
                Textual content("")
                    .body(maxWidth: .infinity)
                    .body(peak: 35)
                    .padding(10)
                    .background(Shade(pink: 238/255, inexperienced: 238/255, blue: 239/255))
            }
            .body(maxWidth: .infinity)
        }
        .body(maxWidth: .infinity)
        .background(Shade(pink: 255/255, inexperienced: 254/255, blue: 185/255))
        .padding(.horizontal)
    }
}

struct SkyBlueView: View {
    @Binding var weightedPriceUsagePercent: String
    @Binding var wacSubWACUnitPricePercent: String
    @Binding var pvpUnitPricePercent: String
    @Binding var totalPercent: String
    var physique: some View {
        HStack {
            Group {
                Textual content("Utilization %")
                
                HStack {
                    Spacer().body(width: 10)
                    TextField("Proportion", textual content: $weightedPriceUsagePercent)
                        .textFieldStyle(.plain)
                        .body(maxWidth: .infinity, maxHeight: .infinity)
                }
                .background(Rectangle().fill(Shade.white))
                .body(peak: 35)
                
                HStack {
                    Spacer().body(width: 10)
                    TextField("Proportion", textual content: $wacSubWACUnitPricePercent)
                        .textFieldStyle(.plain)
                        .body(maxWidth: .infinity, maxHeight: .infinity)
                }
                .background(Rectangle().fill(Shade.white))
                .body(peak: 35)
                .padding(10)
                
                HStack {
                    Spacer().body(width: 10)
                    TextField("Proportion", textual content: $pvpUnitPricePercent)
                        .textFieldStyle(.plain)
                        .body(maxWidth: .infinity, maxHeight: .infinity)
                }
                .background(Rectangle().fill(Shade.white))
                .body(peak: 35)
                
                ZStack {
                    HStack {
                        Spacer().body(width: 10)
                        TextField("", textual content: $totalPercent)
                            .textFieldStyle(.plain)
                            .body(maxWidth: .infinity, maxHeight: .infinity)
                    }
                    .background(Rectangle().fill(Shade.white))
                    .body(peak: 35)
                    .border((Shade(pink: 183/255, inexperienced: 181/255, blue: 182/255)), width: 2)
                    .padding(10)

                }
                .body(maxWidth: .infinity)
                .body(peak: 35)
                .padding(10)
                .background(Shade(pink: 238/255, inexperienced: 238/255, blue: 239/255))
            }
            .body(maxWidth: .infinity)
        }
        .body(maxWidth: .infinity)
        .background(Shade(pink: 199/255, inexperienced: 229/255, blue: 243/255))
        .padding(.horizontal)
    }
}


struct GreenView: View {
    @Binding var weightedPriceCalculated: String
    @Binding var wacSubWACUnitPriceCalculated: String
    @Binding var pvpUnitPriceCalculated: String
    @Binding var totalCalculated: String
    var physique: some View {
        HStack {
            Group {
                Textual content("Weighted Value")
                    .body(maxWidth: .infinity)
                Textual content(weightedPriceCalculated)
                    .body(maxWidth: .infinity)
                Textual content(wacSubWACUnitPriceCalculated)
                    .body(maxWidth: .infinity)
                Textual content(pvpUnitPriceCalculated)
                    .body(maxWidth: .infinity)
                
                ZStack {
                    Textual content(totalCalculated)
                        .body(maxWidth: .infinity)

                }
                .body(maxWidth: .infinity)
                .body(peak: 25)
                .padding(10)
                .background(Shade(pink: 76/255, inexperienced: 174/255, blue: 234/255))
            }
            .body(maxWidth: .infinity)
        }
        .body(maxWidth: .infinity)
        .background(Shade(pink: 195/255, inexperienced: 231/255, blue: 145/255))
        .padding(.horizontal)
    }
}


remaining class LandingViewModel: ObservableObject {
    @Printed var gridDataArray: [LandingViewDataModel] = []
    
    init(gridDataArray: [LandingViewDataModel]) {
        self.gridDataArray = gridDataArray
        self.gridDataArray.append(LandingViewDataModel(productLabel: "Endo Product",
                                                       productName: "Endo product one thing",
                                                       productId: "Endo product ID",
                                                       weightedProductPrice: "122.43",
                                                       weightedPriceUsagePercent: "30",
                                                       weightedPriceCalculated: "",
                                                       wacSubWACUnitPrice: "111.33",
                                                       wacSubWACUnitPricePercent: "20",
                                                       wacSubWACUnitPriceCalculated: "",
                                                       pvpUnitPrice: "222.33",
                                                       pvpUnitPricePercent: "50",
                                                       pvpUnitPriceCalculated: "",
                                                       totalPercent: "",
                                                       totalCalculated: ""))
        
        self.gridDataArray.append(LandingViewDataModel(productLabel: "Competitor 1",
                                                       productName: "Competitor 1",
                                                       productId: nil,
                                                       weightedProductPrice: "198.43",
                                                       weightedPriceUsagePercent: "10",
                                                       weightedPriceCalculated: "",
                                                       wacSubWACUnitPrice: "987.33",
                                                       wacSubWACUnitPricePercent: "70",
                                                       wacSubWACUnitPriceCalculated: "",
                                                       pvpUnitPrice: "876.33",
                                                       pvpUnitPricePercent: "20",
                                                       pvpUnitPriceCalculated: "",
                                                       totalPercent: "",
                                                       totalCalculated: ""))
        
        self.gridDataArray.append(LandingViewDataModel(productLabel: "Competitor 2",
                                                       productName: "Competitor 2",
                                                       productId: nil,
                                                       weightedProductPrice: "445.43",
                                                       weightedPriceUsagePercent: "40",
                                                       weightedPriceCalculated: "",
                                                       wacSubWACUnitPrice: "432.33",
                                                       wacSubWACUnitPricePercent: "20",
                                                       wacSubWACUnitPriceCalculated: "",
                                                       pvpUnitPrice: "456.33",
                                                       pvpUnitPricePercent: "40",
                                                       pvpUnitPriceCalculated: "",
                                                       totalPercent: "",
                                                       totalCalculated: ""))
        
    }
}

struct LandingViewDataModel: Hashable, Equatable {
    let productLabel: String
    var productName: String
    var productId: String?
    
    var weightedProductPrice: String {
        didSet {
            calculate()
        }
    }
    var weightedPriceUsagePercent: String {
        didSet {
            calculate()
        }
    }
    var weightedPriceCalculated: String
    
    var wacSubWACUnitPrice: String {
        didSet {
            calculate()
        }
    }
    var wacSubWACUnitPricePercent: String {
        didSet {
            calculate()
        }
    }
    var wacSubWACUnitPriceCalculated: String
    
    var pvpUnitPrice: String {
        didSet {
            calculate()
        }
    }
    var pvpUnitPricePercent: String {
        didSet {
            calculate()
        }
    }
    var pvpUnitPriceCalculated: String
    
    var totalPercent: String
    var totalCalculated: String
}

extension LandingViewDataModel {
    non-public mutating func calculate() {
        if let flotPrice = Float(weightedProductPrice), let proportion = Float(weightedPriceUsagePercent)  {
            weightedPriceCalculated = "(flotPrice * (proportion / 100))"
        }
        
        if let flotPrice = Float(wacSubWACUnitPrice), let proportion = Float(wacSubWACUnitPricePercent)  {
            wacSubWACUnitPriceCalculated = "(flotPrice * (proportion / 100))"
        }
        
        if let flotPrice = Float(pvpUnitPrice), let proportion = Float(pvpUnitPricePercent)  {
            pvpUnitPriceCalculated = "(flotPrice * (proportion / 100))"
        }
        
        if let weightedPriceUsagePercent = Int(weightedPriceUsagePercent),
           let wacSubWACUnitPricePercent = Int(wacSubWACUnitPricePercent),
           let pvpUnitPricePercent = Int(pvpUnitPricePercent) {
            totalPercent = "(weightedPriceUsagePercent + wacSubWACUnitPricePercent + pvpUnitPricePercent)"
        }
        
        if let weightedPriceCalculated = Float(weightedPriceCalculated),
           let wacSubWACUnitPriceCalculated = Float(wacSubWACUnitPriceCalculated),
           let pvpUnitPriceCalculated = Float(pvpUnitPriceCalculated) {
            totalCalculated = "(weightedPriceCalculated + wacSubWACUnitPriceCalculated + pvpUnitPriceCalculated)"
        }
    }
}

LEAVE A REPLY

Please enter your comment!
Please enter your name here