1. 샘플 프로젝트 생성하기
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
import UIKit
// MARK: - 델리게이트 생성
protocol MyDelegate: AnyObject {
var name: String { get }
}
class MyView: UIView {
weak var delegate: MyDelegate?
// var delegate: MyDelegate?
}
// MARK: - 델리게이트 채택
class DetailViewController: UIViewController, MyDelegate {
var name: String = ""
let myview = MyView()
override func viewDidLoad() {
super.viewDidLoad()
print(#function, #fileID)
myview.delegate = self
view.addSubview(myview)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
print(#function, #fileID)
}
@IBAction func previous(_ sender: Any) {
print(#function, #fileID)
dismiss(animated: true, completion: nil)
}
deinit {
print(#function, #fileID)
}
}
2. 메모리 누수 관련 설정하기
Edit Scheme에 들어가서 Malloc Scribble, Malloc Stack Logging을 체크한다.
3. 확인하기
weak var delegate: MyDelegate? 일 때 (약한참조일때)
프레젠드, 디스미스를 여러번해보면 콘솔에 아래와 같이 deinit이 잘 호출되는 것을 볼 수 있다.
viewDidLoad() MemoryLeak/DetailViewController.swift
previous(_:) MemoryLeak/DetailViewController.swift
viewDidDisappear(_:) MemoryLeak/DetailViewController.swift
deinit MemoryLeak/DetailViewController.swift
viewDidLoad() MemoryLeak/DetailViewController.swift
previous(_:) MemoryLeak/DetailViewController.swift
viewDidDisappear(_:) MemoryLeak/DetailViewController.swift
deinit MemoryLeak/DetailViewController.swift
또한, 메모리 그래프를 클릭하고
디버그 네비게이터를 열고
하단에 show matching content based on fillter string
을 눌러준다. (이건 앱내에서 사용하는 기본 제공 프레임워크 같은 애들을 보여주느냐 마느냐의 여부이다. 얘는 클릭하고 왼쪽에 애는 클릭하지않으면 된다.)
그러면 상태가 아래와 같다. 앱델리게이트와 씬델리게이트 다음엔 뷰컨트롤러만 존재한다. 이제 비교해보자.
weak delegate: MyDelegate? 일 때 (강한참조일때)
똑같이 프레젠트, 디스미스를 여러번 수행한다. 그리고 콘솔을 보면 아래와 같이 deinit이 호출되지 않는 것을 볼 수 있다.
viewDidLoad() MemoryLeak/DetailViewController.swift
previous(_:) MemoryLeak/DetailViewController.swift
viewDidDisappear(_:) MemoryLeak/DetailViewController.swift
viewDidLoad() MemoryLeak/DetailViewController.swift
previous(_:) MemoryLeak/DetailViewController.swift
viewDidDisappear(_:) MemoryLeak/DetailViewController.swift
viewDidLoad() MemoryLeak/DetailViewController.swift
previous(_:) MemoryLeak/DetailViewController.swift
viewDidDisappear(_:) MemoryLeak/DetailViewController.swift
또 같은 화면을 보면 아까와 다르게 앱델리게이트와 씬델리게이트 사이에 디테일 뷰컨트롤러와 디테일 뷰컨트롤러 위에올라간 myView가 (3)이 있는걸 볼 수있다. 아직 메모리에 남아있다는 것이다.
다시 재생해서 추가로 3번 프레젠트, 디스미스를 하고 열어보자. 그러면 (3)이 (6)으로 올라간 것을 볼 수 있다. 메모리가 계속 누수되고 있는 것이다. 이게 쌓이고 쌓이고 또싸이면 터져서 스택오버플로우가 난다.