본문 바로가기

iOS

[iOS] get, set, didSet, willSet in Swift

get, set, didSet, willSet with Swift

 

본 내용을 살펴보기에 앞서 프로퍼티 값을 연산하여 저장하는 Computed Property에 대하여 미리 알고 있어야 한다.

 

이번 시간에는 Swift에서 프로퍼티 초기화에 있어 이용되는 get, set, didSet, willSet 에 대하여 알아보자!

 

각각의 키워드를 보면 대략적인 느낌이 오듯 이는 일반적으로 OOP 패러다임에서 사용하는 getter, setter 메서드다.

 

즉, 프로퍼티 값을 초기화하고 이를 가져오는 기능을 제공한다.

 

get, set in Swift


Swift 내에서 get,set 은 일반적으로 우리가 쓰는 getter, setter 와 매우 유사하다.

 

간단하게 예시를 살펴보도록 한다.

 

var testProperty: Int {
    get {
        return testProperty
    }
    set(value) {
        testProperty = value
    }
}

print(testProperty)     // testProperty의 value 출력
testProperty = 123      // value = 123

 

위와 같이 코드를 작성하면 Xcode IDE에서 경고 혹은 에러를 띄운다.

 

getset이 해당 프로퍼티에 직접적으로 연결되어 있기 때문에 get{}, set{} 에서 testProperty에 접근하면 recursive하게 자기 자신의 get,set이 호출되므로 위와 같이 사용하지 않는다.

 

따라서 이러한 점을 보완하기 위해 저장소 라는 개념을 이용한다.

 

여기서 말하는 저장소란, get, set을 사용할 때 연산된 값을 저장할 변수를 의미한다.

 

var _testProperty: Int  // 실제 값이 저장될 변수

var testProperty: Int {
    get { 
        return _testProperty
    }
    set(value) {
        _testProperty = value
    }
}

 

위 코드에서는 _testProperty 가 실제 값이 저장되는 변수다.

 

외부에서 testProperty의 값에 접근하거나 새로운 값이 할당될 경우 실제로 값이 저장되는 곳은 testProperty 가 아닌 _testProperty이다.

 

즉, testProperty_testProperty 에 값을 저장하기 위해 일차적으로 연산의 결과를 저장하는 '저장소'가 된다.

 

이쯤되면 대략적인 get,set 의 사용목적이 궁금해진다.

 

두 개념은 아래와 같은 목적으로 사용된다.

 

  1. property 초기화시 값 검증

  2. 타 property에 의존하는 property 값을 관리 할 때

  3. private한 property 사용을 위해

 

computed Property를 읽기 전용 권한으로 구현할때는 get 블럭을, 쓰기 전용 권한으로 구현할때는 set 블럭을, 읽기&쓰기 모두 가능하게 하려면 get,set 블럭을 모두 구현해주면 된다.

 

struct Point {

    var x: Int = 0
    var y: Int = 0

    var oppositePoint: Point {
        get {
            return Point(x: -x, y: -y)
        }
        set(value) {
            x = -value.x
            y = -value.y
        }
    }
}

var test: Point = Point(x: 1, y: 2)     // Setter

print(test)                             // Getter : Point(x: 1, y: 2)

test.oppositePoint = Point(x:-3, y:-4)  // Setter 

print(test)                             // Getter : Point(x: 3, y: 4)

 

didSet, willSet in Swift


Swift에서는 Property ObserverdidSet, willSet 을 제공한다.

 

이름대로 프로퍼티 값의 변경 직전, 직후에 대한 이벤트를 감지하며 해당 시점에 작업을 수행할 수 있도록 하는 기능을 지원한다.

 

기본적으로 아래와 같이 사용한다.

 

var testProperty: Int = 10 {
    didSet(oldValue) {
        //body , testProperty의 값이 변경된 직후 호출, oldValue에는 이전 testProperty 값이 들어간다.
    }

    willSet(newValue) {
        //body , testProperty의 값이 변경되기 직전에 호출, newValue에는 새로 초기화하고자 하는 값이 들어간다.
    }
}

 

참고로 Property ObserverdidSet, willSet을 사용하기 위해서는 property 값이 반드시 초기화 되어 있어야 한다.

 

두 개념은 Model에서의 변경사항을 View에 반영하고자 할 떄 빈번히 사용된다.

 

간단한 예시를 살펴보도록 한다.

 

class Account {

    var balance: Int = 0 {
        willSet(newValue) {
            print("잔액: \(balance) -> \(newValue) 변경 예정")
        }

        didSet(oldValue) {
            print("잔액: \(oldValue) -> \(balance) 변경 완료")
        }
    }
}

let test = Account()

test.balance = 500

test.balance = 300

/*
output

잔액: 0 -> 500 변경 예정
잔액: 0 -> 500 변경 완료
잔액: 500 -> 300 변경 예정
잔액: 500 -> 300 변경 완료

*/

 

 

잔액을 0으로 초기화해놓고, 재정의 하려고 하면 didSet 과 willSet이 호출되어 각기 맡은 액션을 진행한다.

 

Swift에서 제공하는 get, set, didSet, willSet에 대하여 간단히 알아보았다.

 

이를 활용하면 더욱 편하며 직관적으로 코드를 작성할 수 있다.

 

이상으로 오늘 포스팅을 마치도록 한다.

 

'iOS' 카테고리의 다른 글

[iOS] GCD (Grand Central Dispatch)  (1) 2020.06.24
[iOS] Alamofire 소개 및 데모 예제  (0) 2020.06.23
[iOS] [Swift] Stack과 Queue  (0) 2020.06.11
[iOS] Generic in Swift  (0) 2020.06.10
[iOS] Observer Pattern in Swift  (0) 2020.06.10