Medium - lazy var in ios swift

원문 - Abhimuralidharan

Trend 파악을 Medium 기고문 요약 포스팅 - iOS 스위프트의 lazy var

iOS 개발을 할 때 우리는 응용프로그램이 사용하는 메모리의 총량에 대해 항상 생각해야 합니다. 만약 앱이 복잡하다면 메모리 이슈 때문에 개발자들이 고생할 것입니다. 그러니까 개발자들은 처음부터 메모리 할당을 고려하여 최적화된 코드를 작성해야 합니다. 개발자라면 정말로 필요한 것이 아니라면 시간이 많이 걸리는 작업은 피해야합니다. 이런 복잡한 할당은 시간을 더욱 소비하게 될 것이고 앱의 성능에 심각한 영향을 미칠 것입니다.

스위프트는 이른바 lazy variable을 언어에서 지원하여 시간이 많이 걸리는 작업을 정확한 시간에 수행할 수 있습니다. lazy 변수는 변수가 처음 요청될 때 여러분이 특정한 함수를 이용하며 생성됩니다. 만약 요청되지 않으면 함수도 사용되지 않고 처리시간을 아낄 수 있습니다.

애플 공식 문서는 다음과 같습니다: lazy로 저장된 프로퍼티는 처음으로 사용되기 전까지는 초기 값이 계산되지 않습니다. 당신은 lazy단어를 앞에 붙임으로써 lazy로 저장되는 프로퍼티를 선언할 수 있습니다.

당신은 항상 lazy 프로퍼티를 변수로 선언해야 합니다.(var 키워드를 사용해서요) 왜냐하면 lazy 프로퍼티의 초기 값은 인스턴스 초기화가 끝나도 가져올 수 없기 때문입니다. 상수 프로퍼티는 항상 초기화가 끝나면 값이 있어야 하기 때문에 lazy로 선언할 수 없습니다.

이 것을 설명하기 위해 쉬운 예제를 설명하겠습니다. InterViewCandidate 라는 구조체를 생각해봅시다. 옵셔널 bool변수가 있고 지원자의 분야가 iOS인지 android인지 결정한다고 합시다. iOS, android 이력서 내용은 lazy 변수로 선언됩니다. 그러니까 다음의 코드에서는 지원자가 iOS 개발자라면 iOSResumeDescription 변수는 출력하기 위해 호출될 때 초기화 될 것이고 androidResumeDescription은 nil 값이 될 것입니다.


import UIKit


struct InterviewCandidate {
    var isiOS:Bool?

    lazy var iOSResumeDescription: String = {
        return "I am an iOS developer"
    }()
    lazy var androidResumeDescription: String = {
        return "I am an android developer"
    }()
}

var person1 = InterviewCandidate()
person1.isiOS = true

if person1.isiOS! {
    print(person1.iOSResumeDescription)
} else {
    print(person1.androidResumeDescription)

}

이것은 아주 기본 예제입니다. 만약 우리가 재귀함수를 사용하여 변수를 계산하는 클래스나 구조체가 있고 이런 객체가 1000개가 있다면 성능이나 메모리 문제가 생길 것입니다.

Lazy Stored Property vs Stored Peoperty

저장 프로퍼티보다 lazy 프로퍼티가 뛰어난 점이 몇가지 있습니다.

  1. 레이지 프로퍼티와 연관된 클로저는 프로퍼티를 읽어들일 때만 수행됩니다. 그래서 만약 해당 프로퍼티가 사용되지 않으면 불필요한 할당과 연산을 피할 수 있습니다.
  2. 저장 프로퍼티의 값으로 lazy property를 채울 수 있습니다.
  3. 가장 중요한 것은 lazy 프로퍼티의 클로저 내에서는 self를 사용할 수 있습니다. 사이클을 만들지 않는 이유는 즉시 적용된 클로저의 블록은 \@noescape로 처리되기 때문입니다.

그러나 함수 내에서 self를 사용해야 될 수도 있죠. 여러분이 구조체 대신에 클래스를 사용한다면 [unowned self]를 명시해서 내부 함수가 strong 레퍼런스 사이클을 만들지 않도록 해야 합니다. 아래의 코드를 보시죠

// playground code
import UIKit
import Foundation
class InterviewTest {
var name: String
lazy var greeting : String = { return “Hello \(self.name)” }()
// No retain cycles here ..
init(name: String) {
self.name = name
 }
}
let testObj = InterviewTest(name:”abhi”)
testObj.greeting

당신은 클로저 여부와 상관없이 변수를 참조할 수 있습니다.

lazy var iOSResumeDescription = “I am an iOS developer”

위의 방식으로도 작성할 수 있습니다.

기억하세요, lazy 프로퍼티가 계산되는 시점은 처음으로 요청되고 그들의 값이 저장되었을 때 입니다. 그러니까 iOSResumeDescription을 두번째로 호출하면 이전에 저장된 값이 반환될 것입니다.

Lazy rules:

  • lazy를 let과 사용할 수 없습니다.
  • 연산된 프로퍼티와 사용할 수 없습니다. 왜냐하면 연산된 프로퍼티는 우리가 해당 프로퍼티에 접근할 때 마다 내부의 연산 블록을 수행하고 값을 러틴하기 때문입니다.
  • 구조체나 클래스의 멤버에 대해서만 lazy를 사용할 수 있습니다.
  • Lazy 변수들은 원자적으로 초기화 되지 않기 때문에 스레드에 부적합 합니다.

Summary

  • lazy 저장 프로퍼티의 개념은 최초에 사용될 때만 초기화를 하는 것으로 효율적인 메모리 관리를 위함이다.
  • 초기화 시점이 처음 사용될 때 이므로 let을 사용할 수 없고 연산된 변수와 사용하지 않아야 한다.

© 2019. All rights reserved.

Powered by Hydejack v8.1.1