Property Wrapper

왜 사용하는가?

프로퍼티에 접근할 때, 사람들은 공통적인 패턴으로 접근 함

  • lazy를 통한 value initalized
  • Thread-local stroage를 사용할 때
  • UserDefaults

등등...
어떤 프로퍼티에 접근할때 get이나 set를 사용하지만 코드가 반복될 때가 있는데 property wrapper를 통해 재사용성을 높이고 중복을 없앨 수 있음
 

사용법

@propertyWrapper
struct TwelveOrLess {
    private var num: Int = 0
    
    var wrappedValue: Int {
        get { return num }
        set { num = min (newValue, 12) }
    }
    
    init(wrappedValue: Int) {
        self.wrappedValue = wrappedValue
    }
}

class, enum, struct를 상단에 @propertyWrapper를 붙이고 wrappedValue를 선언. wrappedValue가 프로퍼티에 접근하는 값

struct SmallRectangle {
    
    @TwelveOrLess var town: Int
    
    init(town: Int) {
        self.town = town
    }
}

그리고 해당 로직을 적용할 프로퍼티 앞에 선언한 propertywrapper를 붙이면 된다.
propertyWrapper에 init을 만들지 않으면 propertyWrapper를 사용하는 프로퍼티의 생성자 타입이 propertyWrapper 타입이 되어버린다.
 

@propertyWrapper
struct TwelveOrLess {
    private var num: Int = 0
    
    var wrappedValue: Int {
        get { return num }
        set { num = min (newValue, 12) }
    }
}

struct SmallRectangle {
    
    @TwelveOrLess var town: Int
    
}

또한 생성자 파라미터의 이름이 wrappedValue가 아닐 경우에도 생성자의 타입이 propertyWrapper 타입이 돼버린다.

@propertyWrapper
struct TwelveOrLess {
    private var num: Int
    
    var wrappedValue: Int {
        get { return num }
        set { num = min (newValue, 12) }
    }
    
    init(input: Int) {
        self.wrappedValue = input
    }
    
}

struct SmallRectangle {
    
    @TwelveOrLess var town: Int
    
}

그래서 SmallRectangle의 생성자 타입이 propertyWrapper 타입일 때, 다음과 같이 propertyWrapper 생성자를 만들면 올바르게 타입이 나오는 걸 볼 수 있다.

@propertyWrapper
struct TwelveOrLess {
    private var num: Int
    
    var wrappedValue: Int {
        get { return num }
        set { num = min (newValue, 12) }
    }
    
// 호출시 보이는 인자값 이름이 wrappedValue여야 한다.
    init(wrappedValue input: Int) {
        self.wrappedValue = input
    }
    
	init(wrappedValue: Int) {
        self.wrappedValue = input
    }
}

struct SmallRectangle {
    
    @TwelveOrLess var town: Int
    
}

propertyWrapper 자체에서 생성자를 불러올 수 있음

@propertyWrapper
struct TwelveOrLess {
    var num: Int
    
    var wrappedValue: Int {
        get { return num }
        set { num = min (newValue, 12) }
    }
}

struct SmallRectangle {
    
    @TwelveOrLess(num: 10)
    var town: Int
    
}

이 경우 Smallrectangle의 town 프로퍼티는 초기화가 된 것