Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to bind to Published property with private setter

Here is my data model:

@MainActor
class TestModel: ObservableObject {
    @Published private(set) var data = ""
    
    private func randomAlphaNumericString(length: Int) -> String {
        let allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        let allowedCharsCount = UInt32(allowedChars.count)
        var randomString = ""

        for _ in 0 ..< length {
            let randomNum = Int(arc4random_uniform(allowedCharsCount))
            let randomIndex = allowedChars.index(allowedChars.startIndex, offsetBy: randomNum)
            let newCharacter = allowedChars[randomIndex]
            randomString += String(newCharacter)
        }

        return randomString
    }
    
    func update() {
        data = randomAlphaNumericString(length: 10)
    }
}

And the application view is:

import SwiftUI

struct TestView: View {
    @StateObject var model = TestModel()
    
    var body: some View {
        VStack {
            TestSubView(textData: $model.data)
            Button("Update") {
                model.update()
            }
        }
    }
}

where a subview is defined as follows:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import SwiftUI

struct TestSubView: View {
    @Binding var textData: String
    
    var body: some View {
        Text("Data : \(textData)")
    }
}

With this code I get a compilation error because of a private setter for a model field data. How can I stay with a private setter and get this binding to work? What is the correct pattern to follow?

>Solution :

I think you don’t need a @Binding here at all. It looks like you TextSubView is not updating the text. You just want to make sure that it updates when the text updates.

So change your view like this…

import SwiftUI

struct TestView: View {
    @StateObject var model = TestModel()
    
    var body: some View {
        VStack {
            TestSubView(textData: model.data)
            Button("Update") {
                model.update()
            }
        }
    }
}

And your TextSubView like this…

import SwiftUI

struct TestSubView: View {
    let textData: String
    
    var body: some View {
        Text("Data : \(textData)")
    }
}

Doing this removes anything in the code that allows your view to update the text. Which you weren’t doing anyway.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading