You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
classDog{varname:Stringvarowner:Person?init(name:String){self.name = name
}deinit{print("\(name) 메모리 해제")}}classPerson{varname:Stringvarpet:Dog?init(name:String){self.name = name
}deinit{print("\(name) 메모리 해제")}}
인스턴스를 각자만들면
bori변수는 bori의 RC를 1증가시킴
gildong변수는 gildong의 RC를 1증가시킴
bori의 owner가 gildong의 RC를 1증가시킴(gildong RC = 2)
gildong의 pet이 bori의 RC를 1증가시킴(bori RC = 2)
이런 상황에서 bori변수와 gildong변수에 nil을 할당하더라도 RC가 1씩 줄어들어도
서로가 서로를 가리켜 메모리에서 해제되지 않는다
💡 객체가 서로를 참조하는 강한 참조 사이클로 인해
변수의 참조에 nil을 할당해도 메모리 해제가 되지 않는
메모리 누수(Memory Leak)의 상황이 발생
Memory Leak의 해결방안
RC를 고려하여, 참조 해제 순서를 주의해서 코드 작성 → 실수할 가능성이 높음 비추
Weak Reference (약한 참조)
가리키지만 RC를 증가시키지 않는 방법
메모리 누수(Memory Leak)현상의 해결
약한참조
weak varowner:Person?
weak varpet:Dog?
→ Person을 가리키지만 RC를 증가시키지 않음
→ 약한 참조의 경우, 참조하고 있던 인스턴스가 사라지면, nil로 초기화 되어있음
gildong =nil
bori?.owner // gildong만 메모리 해제시켰음에도 ===> nil
밸류(Value) 타입 캡처와 캡처리스트
클로저는 자신이 사용할 외부의 변수를 캡처함
varnum=1
// 클로저를 변수에 담는 순간 클로저는 heap영역에 저장된다
// num이라는 변수를 캡처한다 -> 변수의 주소값을 가리키고 있다
letvalueCaptureClosure={print("밸류값 출력(캡처): \(num)")}
num =7valueCaptureClosure() // result : 밸류값 출력(캡처): 7
num =1valueCaptureClosure() // result : 밸류값 출력(캡처): 1
→ 만약에 캡쳐 리스트를 사용하게 되면 주소값이 아닌 값 자체를 복사해서 가지고 있다
// 이미 위에서 1이라는 num의 값을 복사해서 가지고 와 있는 상태
letvalueCaptureListClosure={[num]inprint("밸류값 출력(캡처리스트): \(num)")}
// num에 7을 할당하더라도 num 1을 복사해서 가지고 있기 때문에 1을 출력
num =7valueCaptureListClosure() // 몇을 출력할까요? = 1
1️⃣WWDC 영상 요약
Value type, Reference type
Value type
Reference type
Strong, Weak, Unowned
strong
weak
unowned
약한 참조가 필요한 경우 weak을 사용하고 옵셔널 바인딩으로 안전하게 추출하는 것이 권장됨
Automatic Reference Counting (ARC)
Object lifetimes in Swift are use-based.
마지막 사용 이후 RC가 0이 되며 메모리에서 해제되므로 최소한의 lifetime을 보장받음
Examples
Memory leak 발생 예시
Person, Account의 RC가 1씩 남으므로 Memory leak 발생
weak 사용으로 해결
Person 해제 -> Account RC = 0 -> Account 해제
또 다른 문제 발생 예시
showAccount( ) 실행 전에 Person이 메모리에서 해제되어 weak으로 선언된 account.person이 nil로 초기화되어 문제 발생 강제 언래핑의 문제로 생각하여 옵셔널 바인딩으로 해결하려 한다면 보이지 않는 버그로 상황이 더 악화됨
Safe Techniques
withExtendedLifetime( )
defer 키워드를 사용하면 현재 스코프의 끝까지 Lifetime을 연장시킬 수 있음 하지만 정확성을 전적으로 개발자에게 부담시키고 유지보수 비용이 증가할 수 있음 따라서 더 좋은 API로 클래스를 다시 디자인하는 것을 권장
Redesign to access via strong reference
Redesign to avoid weak / unowned reference
사이클을 해결하려 하는 것보다 사이클 자체를 만들지 않는 것이 좋음 사이클 구조 -> 트리 구조로 변환
2️⃣ARC정리
스위프트의 메모리 관리 모델
인스턴스를 하나씩 찍어내면 heap영역에 choco인스턴스 bori인스턴스가 올라감
→ 옵셔널 타입으로 설정한 이유는 nil을 할당할 수 있어야하기 때문
choco의 RC(레퍼런스 카운트)는 1이 되고 bori의 RC도 1이 된다
choco와 bori변수는 메모리 주소를 가지고 있는데 nil로 할당해주면 RC가 0이 된다
→ deinit이 호출된다
Memory Leak(메모리 누수) 현상
인스턴스를 각자만들면
이런 상황에서 bori변수와 gildong변수에 nil을 할당하더라도 RC가 1씩 줄어들어도
서로가 서로를 가리켜 메모리에서 해제되지 않는다
💡 객체가 서로를 참조하는 강한 참조 사이클로 인해변수의 참조에 nil을 할당해도 메모리 해제가 되지 않는
메모리 누수(Memory Leak)의 상황이 발생
Memory Leak의 해결방안
메모리 누수(Memory Leak)현상의 해결
→ Person을 가리키지만 RC를 증가시키지 않음
→ 약한 참조의 경우, 참조하고 있던 인스턴스가 사라지면, nil로 초기화 되어있음
밸류(Value) 타입 캡처와 캡처리스트
→ 만약에 캡쳐 리스트를 사용하게 되면 주소값이 아닌 값 자체를 복사해서 가지고 있다
참조(Reference) 타입 캡처와 캡처리스트
강한 참조 사이클 문제의 해결
⭐️객체 내에서 클로저의 사용⭐️
→ ✅클로저 내에서 객체의 속성 및 메서드에 접근 시에는 "self키워드"를 ⭐️반드시⭐️ 사용해야함✅
💡 무조건 self를 붙여야하는데 방식이 두가지가 있다 1. self.name 2. [self] in name→ 비동기 처리를 진행할때 변수의 주소를 캡쳐하고 있으면 2번 쓰레드에서 독립적으로 작업을 할 수가 없게된다 그렇기 때문에 객체를 가리키고 있어야한다(강한참조가 필요)
캡처리스트 실제 사용 예시
함수 실행의 결과 → 글로벌큐에서 출력하기, 뷰컨, 뷰컨 메모리 해제
weak self라면 → 뷰컨 메모리 해제, 글로벌큐에서 출력하기: nil
Reference
The text was updated successfully, but these errors were encountered: