Property Wrappers in Swift
It's really easy to make a property wrapper in Swift to automatically modify a property.
Here's an example, with tests to show how it works.
@NonEmpty
Example
Say I want to ensure an optional String can't be empty - it's either nil
, or it's got a value, but that value can't be ""
(because then it's got the same meaning as nil
, and I don't want to have to check both values when I'm using it). I can create a @NonEmpty
property wrapper which makes sure a String matches that requirement.
Usage in Code
@NonEmpty var myString = "" // gets changed to `nil`
@NonEmpty var myString = nil // keeps its value as `nil`
@NonEmpty var myString = "Killie won the Championship in 2021/22" // 🏆 - keeps its original value
The Code
@propertyWrapper public struct NonEmpty {
public var wrappedValue: String? {
didSet {
wrappedValue = getNonEmptyStringOrNil(from: wrappedValue)
}
}
public init(wrappedValue: String?) {
self.wrappedValue = getNonEmptyStringOrNil(from: wrappedValue)
}
private func getNonEmptyStringOrNil(from inputString: String?) -> String? {
if let inputString = inputString, !inputString.isEmpty {
return inputString
} else {
return nil
}
}
}
The Tests
class NonEmptyPropertyWrapperTests: XCTestCase {
func testNonEmpty_givenNilString_returnsNilString() {
@NonEmpty var testString = nil
XCTAssertNil(testString)
}
func testNonEmpty_givenEmptyString_returnsNilString() {
@NonEmpty var testString = ""
XCTAssertNil(testString)
}
func testNonEmpty_givenWhitespaceString_returnsOriginalString() {
@NonEmpty var testString = " "
XCTAssertEqual(testString, " ")
}
func testNonEmpty_givenNonEmptyString_returnsOriginalString() {
@NonEmpty var testString = "Test"
XCTAssertEqual(testString, "Test")
}
}
Links
There's usually a Swift By Sundell link for anything Swift-related and this is no different. Here's a great example of how to make a @Capitalized
wrapper for a String
, a generic @UserDefaultsBacked
wrapper, and much more info on how it works:
Published on 25 May 2022