Having trouble writing a property wrapper for Swift Strings

56 Views Asked by At

Trying to write a property wrapper like so:

@propertyWrapper struct LessThanSixteen<String> {
    var value: String
    
    var wrappedValue: String {
        get { value }
//        set { value = }
    }
    
    init(wrappedValue: String) {
        var x = wrappedValue
        self.value = (wrappedValue.count < 16) ? wrappedValue : wrappedValue.dropLast(wrappedValue.count - 16)
    }
}

The line self.value = (wrappedValue.count < 16) ? wrappedValue : wrappedValue.dropLast(wrappedValue.count - 16) is throwing 2 errors. "Value of type 'String' has no member 'count'" and "Value of type 'String' has no member 'dropLast'". I don't understand why the compiler says that.

if I write this code outside of a @propertyWrapper struct:

let someString = "this string is more than 16 characters long"
let someSubstring = String(someString.dropLast(someString.count - 16))

I get no such compiler errors. I don't understand why I can't do that code inside the property wrapper.

1

There are 1 best solutions below

1
On BEST ANSWER

struct LessThanSixteen<String> declares a generic type, with a generic type parameter named "String", in the same way that Array<Element> is a generic type with a type parameter named Element.

Therefore, the word String inside the property wrapper refers to the generic type parameter, not the Swift built-in String type (and is totally unrelated to it).

"What types of properties can a property wrapper be applied on" is not determined by generic type parameters. It is determined by the type of wrappedValue. Of course, if the type of wrappedValue is a generic type parameter, then the property wrapper can be applied to properties with types that the type parameter can be.

If you want a property wrapper that only works on Strings, just make wrappedValue a String.

@propertyWrapper struct LessThanSixteen {
    private var value: String
    
    var wrappedValue: String {
        get { value }
        set {
            value = String(newValue.prefix(16))
        }
    }
    
    init(wrappedValue: String) {
        var x = wrappedValue
        self.value = String(wrappedValue.prefix(16))
    }
}