티스토리 뷰

Mobile/iOS

swift lazy

out of coding 2018. 5. 7. 23:31

스위프트에는 지연변수가 존재합니다. 물론 kotlin에도 있고요...

왜 둘이 비슷한지에 대한 문제는 더 이상 이야기 하지 않겠습니다. ㅎ


일반적으로 우리는 이것을 사용할 때에 lazy var를 이용합니다.


지연변수라고 함은 이 변수를 처음으로 접근할 경우에 초기화를 시키는 작용을 하는 변수를 이야기 합니다.


일반적으로 class를 생성할때에는 무조건 초기화가 이루어져 있어야 합니다.


1
2
3
4
5
6
7
8
9
10
class TestA {
 
    var text1: String
    var text2: String
 
    init(text2: String) {
        self.text2 = text2
        self.text1 = "Add : \(text2)"
    }
}
cs


꼭 초기화를 하여야 합니다.


let test = TestA()


이렇게 하였는데, 두개의 변수를 초기화를 하고 시작합니다.


이것이 무슨 문제인가 싶기도 하겠지만, 정말 큰문제가 아닐수도 있습니다.

아주 미묘한 문제이기 때문이죠. 


왜냐면 지금 사용하지도 않는 초기 값을 먼저 넣어 버렸습니다.

솔찍히 따지자면 text1은 지금 사용할 값이 아니고, 추후에 사용할때에 가져가서 사용하면 됩니다.


이것을 setter, getter을 이용하여서 다르게 표현이 가능합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class TestA {
 
    private var _text1: String?
    var text1: String {
        get {
            if _text1 == nil {
                _text1 = "Add : \(text2)"
            }
            return _text1!
        }
        set {
            _text1 = newValue
        }
    }
    var text2: String
 
    init(text2: String) {
        self.text2 = text2
    }
}
cs


뭔가를 하기 위해서 쓸모 없는 부분을 너무 많이 타이핑을 하였습니다. 전혀 스위프트 스럽지않죠.

더군다나 _text1이라는 배킹필드를 이용하고 있습니다.


그렇다면 lazy var를 이용하여 봅시다.


1
2
3
4
5
6
7
8
9
10
class TestA {
 
    private var _text1: String?
    lazy var text1: String = "Add : \(self.text2)"
    var text2: String
 
    init(text2: String) {
        self.text2 = text2
    }
}
cs


할게 없는 수준으로 코드가 변화됩니다.


이렇게 사용하는 방법도 있지만. 여러개의 계산을 통해서 값을 가지고 있어야 할 경우가 있습니다.

이러한 경우에는 다음과 같이 closure를 이용합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class TestA {
 
    private var _text1: String?
    lazy var text1: String = {
        if text2 == "AAA" {
            return "Add : \(self.text2)"
        } else {
            return "Not AAA Add : \(self.text2)"
        }        
    }()
    var text2: String
 
    init(text2: String) {
        self.text2 = text2
    }
}
cs


무언가 제가 굉장히 더럽게 코드를 만들어 두기는 했습니다만... 저런 방법으로 클로저 안에서 값을 만들어서 리턴이 가능하게 할수 있다는 표현입니다.


자... 그런데 클로저에는 [weak self]를 꼭 붙여주는 습관을 가지는게 좋은데 위의 제 코드에서는 지금 넣지 않고 동작을 시켰습니다. 이유가 무엇일까요?


그건 lazy 자체는 self가 완전히 초기화가 이루어지고 나중에 호출이 된다는 확신이 있기 때문에 가능한것입니다. 그래서 lazy 변수의 초기화에 사용되는 클로저에는 @noescape가 자동적으로 적용이 되는것이구요. 그래서 외부에서 접근하는것이 아니므로 캡쳐를 할 필요가 없습니다.


그렇다면 lazy let은 존재하지 않나요?

네 존재하지 않습니다. ㅎㅎ


그렇지만 거의 엇비슷하게 사용할수 있는데요.


static let을 이용하는 방법입니다.


1
2
3
4
5
class Dog {
    static let name: String = {
        return "Malbok"
    }()
}
cs


이렇게 사용하게 되면 다른 변수들이 모두 초기화가 되고 사용이 가능합니다. 참고하세요.



'Mobile > iOS' 카테고리의 다른 글

ScrollViewDelegate 호출되는 시점  (0) 2018.05.15
고차함수의 lazy 이용  (0) 2018.05.07
playground 팁 몇가지  (0) 2018.05.04
TestFlight is Currently Unavailable  (0) 2018.05.03
presentedViewController, presentingViewController  (0) 2018.05.02
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함