일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Swift Package Manager
- UIViewControllerTransitioningDelegate
- Side Menu
- ViewBuilder
- 기존 앱
- swift
- scrolling tab
- Tuist
- url 추적
- List
- detect url
- UIPresentationController
- oberve url
- DevelopmentRegion
- transformation.map
- development language
- Android
- convert base64
- 개발자 면접
- ios
- url 관찰
- notifychanged
- 스크롤 탭
- DataBinding
- GeometryReader
- pod install
- base64 변환
- swift #swift keychain #keychain 사용법
- SwiftUI
- 상단 탭바
- Today
- Total
버그 잡이
swift - guard let self = self vs self?. 본문
[weak self] 를 사용할 때, self를 처리하는 방법에는 두 가지가 있습니다.
'guard let self = self' 와 'self?.'
"무엇을 쓰는 것이 좋을까요?"
결론부터 말씀드리면 상황에 따라 다릅니다.
"guard let self = self"
먼저, 클로저 시작 부분에 'guard let self = self'를 쓰는 것은 "deallocation delay"를 발생시킬 수 있습니다.
deallocation delay 는 클로저가 참조하고 있는 객체의 메모리 해제를 지연시키는 현상을 말합니다.
클로저 안에서 이미지를 로드 하는 등의 시간이 오래 걸리는 작업이 있다면 클로저 안의 로직을 수행하는 도중에 self 인스턴스가 해제될 수 있는 것 입니다.
그런데 guard let으로 self 를 체크하면 self에 대한 강한 참조가 생기고 이후 클로저가 종료될 때까지 self의 해제를 지연시킵니다.
func process(image: UIImage, completion: @escaping (UIImage?) -> Void) {
DispatchQueue.global(qos: .userInteractive).async { [weak self] in
guard let self = self else { return }
// perform expensive sequential work on the image
let rotated = self.rotate(image: image)
let cropped = self.crop(image: rotated)
let scaled = self.scale(image: cropped)
let processedImage = self.filter(image: scaled)
completion(processedImage)
}
}
위 코드를 예로 살펴보면,
guard let self = self 로 self 를 체크했기 때문에 클로저 안에서는 self에 대한 강한 참조가 생기고
self는 해당 클로저가 종료될때까지 메모리에서 해제되지 않습니다.
하지만 image 처리 관련된 무거운 로직이 실행되는 도중에 viewController는 언제든지 해제될 수 있습니다.
이때 viewController가 dismiss 되어도 클로저에서 강한 참조로 잡고 있기 때문에 클로저가 종료될때까지 viewController는 메모리에세 해제될 수 없습니다.
"self?."
반면 self?. 은 self?가 걸린 각 경우마다 self에 대한 nil 체크를 합니다. nil인 경우 해당 메서드를 스킵하고 다음 줄로 넘어갑니다.
func process(image: UIImage, completion: @escaping (UIImage?) -> Void) {
DispatchQueue.global(qos: .userInteractive).async { [weak self] in
// perform expensive sequential work on the image
let rotated = self?.rotate(image: image)
let cropped = self?.crop(image: rotated)
let scaled = self?.scale(image: cropped)
let processedImage = self?.filter(image: scaled)
completion(processedImage)
}
}
클로저 내부 로직 실행 중에 self인 viewController가 dismiss 되면 self와 관련된 메서드는 skip 하고 넘어갑니다.
결론
사소한 차이일 수 있지만 이를 구분해서 쓰면
메모리 누수 또는 데이터 손상을 방지할 수 있습니다.
viewController 가 해제된 이후에 불필요한 작업이 진행되는 것을 피하고 싶다면 → self?.
반대로 객체가 해제되기 전에 모든 작업을 완료하고 싶다면 → guard let
*참고
https://medium.com/flawless-app-stories/you-dont-always-need-weak-self-a778bec505ef
'Swift' 카테고리의 다른 글
Swift - async / await & async let 기초 (0) | 2021.07.08 |
---|---|
swift - image button inset (이미지 버튼 inset 주기) (0) | 2021.01.23 |
Swift에서 Property Wrapper 시작하기 #UserDefaults # projectedValue (0) | 2020.11.28 |
Swift - 스크롤뷰(scorllView)를 구현하기 위한 2가지 방법 (0) | 2020.11.01 |
Swift - Attributed String으로 특정 글자만 색상 바꾸기 (0) | 2020.10.06 |