Inconsistent behavior involving a custom property wrapper, some string modifications work, some don't.

Hi guys,

I'm trying to figure out why I can use some string modifications on a custom property wrapper but not others. My end goal is to try and encapsulate logic on TextFields that I can use across projects and property wrappers seemed like the answer, but I'm getting inconsistent results.

I have the following code:

Code Block
import SwiftUI
import Combine
struct ContentView: View {
    @StateObject var vm = FormDataViewModel()
    var body: some View {
        Form {
            TextField("Name", text: $vm.name)
        }
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
class FormDataViewModel: ObservableObject {
    @CustomWrapper var name: String = ""
    private var nameObserver: AnyCancellable?
    init() {
        nameObserver = _name.$value.sink {_ in
            self.objectWillChange.send()
        }
    }
}
@propertyWrapper
public class CustomWrapper {
    @Published var value: String
    public var wrappedValue: String {
        get { value }
        set {
            value = newValue.filter({$0 != "s"})
            print("Value: \(value)")
        }
    }
    public var projectedValue: AnyPublisher<String, Never> {
        return $value
            .eraseToAnyPublisher()
    }
    public init(wrappedValue: String) {
        value = wrappedValue
    }
}


As the code currently sits, if I type into the TextField the lower case 's' actually appears, and only disappears when I type something else, despite the print statement showing the correct value (without the s).

If I change this line:

Code Block
value = newValue.filter({$0 != "s"})


to this:

Code Block
value = String(newValue.prefix(5))


Then start typing in the text field, the text field shows far more than 5 characters, it'll show however many characters I type, but value printed out only shows only 5.

If I switch out the code to this:

Code Block
value = newValue.uppercased()


Everything works as expected. All lowercase text I enter is immediately uppercased. No delays, no phantom entries like with filter, it just works.

Does anyone know why this happens? Is it a bug? Is it my code?