swift 기본 문법

Swift lazy 알아보기

끄적.. 2022. 8. 31. 14:35
반응형

lazy 저장 프로퍼티는 처음 사용되지 전까지 초기값이 계산되지 않는 프로퍼티이다.(메모리에 올라가지 않는다.) 

변수(var) 앞에 lazy를 선언함으로써 사용할 수 있다. 

 

lazy를 변수 앞에 사용해야 하는 이유??

초기 값은 인스턴스 초기화가 완료 될 때까지 검색되지 않을 수 있기 때문에 변수로 선언해야한다.

상수(let)은 초기화가 완료되기 전에 항상 값을 가지고 있는 상태이어야 하기 떄문에 lazy로 선언할 수 없다. 

 

struct Hello {
    init() {
        print("Hello 생성")
    }
}

struct Hello2 {
    init() {
        print("Hello2 생성")
    }
}

struct Hi {
    var name: String
    
    //lazy
    //lazy 키워드를 사용하면 인스턴스 생성이 바로 되지 않는다.
    lazy var hello = Hello()
    //lazy 키워드가 없을 때는 Hi가 생성될 때 Hello2도 같이 인스턴스 생성이 된다.
    var hello2 = Hello2()
    
    init(_ name: String) {
        self.name = name
        print("HI 생성\(name)")
    }
}

var hi = Hi("")
//Hello2 생성
//HI 생성
//lazy 키워드는 나중에 직접 생성 해줘야 한다.
hi.hello
//Hello 생성

lazy 키워드가 없을 때는 Hi struct가 생성될 때, Hello2도 함께 생성되는 것을 볼 수 있다

Hi struct만 생성한 시점에서는 lazy 키워드에 있는 값은 생성되지 않았다. 

 

hi.hello를 직접 생성한 순간

lazy 키워드가 메모리에 올라가서 프린트가 찍히는 것을 볼 수 있다. 

 

 

lazy 고려사항

1. lazy는 반드시 var(변수)와 함께 사용해야 한다. 

위에서 말한 것과 같이 lazy 변수는 초기값이 나중에 생기기 때문에 let으로 선언이 불가능하다. 

 

2. struct, class 에서만 사용이 가능하다. 

 

3. Computed Property에 사용될 수 없다. 

lazy는 처음 사용될 때 메모리에 값을 올리고 그 이후에 계속 메모리에 올라온 값을 사용한다. 때문에 값을 연산하는 computed property에는 사용할 수 없다. 

 

4. lazy에 특별한 연산을 통해 값을 넣어주기 위해서는 클로저를 사용한다. 

기본적으로 일반 변수는 클래스가 생성된 이후에 접근이 가능하기 때문에 클래스내의 다른 메소드나 프로퍼티에는 self를 통해 접근이 불가능하다. 하지만 lazy를 이용하면 생성 후 추후 접근이라는 의미이기 때문에 클로저 내에서 self로 접근이 가능하다. 

 

class Person {
    var name: String
    lazy var greeting: String = {
         return "Hello my name is \(self.name)"
    }()
    
    init(name: String) {
        self.name = name
    }
}

var me = Person(name: "Ann")
print(me.greeting)

me.name = "Chris"

print(me.name)
print(me.greeting)

//Hello my name is Ann
//Chris
//Hello my name is Ann

다음 코드를 보면 ()초기화를 통해 즉시 실행한 후 결과를 돌려주고 끝나버리기 때문에 메모리 누수의 걱정이 없다. 

 

만약 값을 바꿔주고 싶다면 타입을 string이 아닌 클로저 자체로 만들어주면 가능하다. 

 

 

class Person2 {
    var name: String
    
    lazy var greeting: () -> String = { [weak self] in
        return "Hello my name is \(self?.name ?? "")"
    }
    init(name: String) {
        self.name = name
    }
}

var me2 = Person2(name: "apple")

print(me2.greeting())

me2.name = "banana"

print(me2.greeting())
//Hello my name is apple
//Hello my name is banana

클로저 자체를 담고 있는 변수라면 [weak self]를 통해 메모리 누수 방지를 해줘야 한다. 

클로저 자체가 메모리에 올라가 있고 self는 내부에서 클로저를 참고하고 있기 때문에 결과값이 바뀌게 된다. 

 

참고

https://abhimuralidharan.medium.com/lazy-var-in-ios-swift-96c75cb8a13a

 

lazy var in ios swift

This article explains the working of lazy var in swift.You must have some knowledge in closures.

abhimuralidharan.medium.com

https://baked-corn.tistory.com/45

 

[Swift] lazy Variables

Lazy variables 이전의 글들을 보셨거나 스위프트 문법 공부를 해보신 분들이라면 스위프트에서 메모리는 굉장히 예민한 주제인 것을 알 수 있습니다. 저 역시 그렇게 느꼈고, 그런 예민함이 보다

baked-corn.tistory.com

 

반응형