Swift의 참조 주기
개발자를 위한 메모리 관리는 일반적으로 사소한 일이 아닙니다. ARC( Automatic Reference Counting ) 덕분에 iOS 개발자가 메모리를 쉽게 관리할 수 있습니다. 대부분의 시간 동안 작동합니다. 그러나 참조 주기는 매우 까다로우며 많은 숙련된 개발자가 그러한 실수를 하는 것을 보았습니다.
공식 문서는 주로 두 개체 A<->B 간의 기본 참조 순환에 대해 설명합니다. 이 글에서 보여드릴 것은 3~4개의 객체 사이의 참조 순환인데, 이는 더 알아보기 어렵습니다.
메모리 누수가 있는 앱
데모는 두 개의 화면이 있는 매우 간단한 iOS 프로젝트입니다. 첫 번째 화면인 "InitialViewController"에서 사용자는 버튼을 클릭하여 두 번째 화면인 "SampleViewController"를 시작한 다음 닫기 버튼을 클릭하여 두 번째 화면을 닫을 수 있습니다. 두 번째 화면은 VIP 클린 아키텍처를 사용하여 코딩됩니다.
사용자가 앱을 사용하는 동안 메모리가 누수됩니다. Xcode의 "디버그 메모리 그래프" 기능의 다음 화면에서 "SampleViewController", "SamplePresenter", "SampleInteractor" 및 "SampleRouter" 각각의 5개 인스턴스가 누출된 것을 볼 수 있습니다. 너무 많은 메모리 누수가 발생하면 앱이 시스템에 의해 종료되며 이는 앱 개발자에게 매우 당혹스러운 일이 될 것입니다.
여러 개체 내의 참조 순환
아래의 소스 코드를 자세히 살펴보고 메모리 누수가 발생하는 이유를 알아보겠습니다.
class SampleViewController: UIViewController, SampleViewControllerInterface {
var interactor: SampleInteractorInterface?
// omitted the rest for simplicity
}
class SampleInteractor: SampleInteractorInterface {
var presenter: SamplePresenterInterface?
// omitted the rest for simplicity
}
class SamplePresenter: SamplePresenterInterface {
var viewController: SampleViewControllerInterface?
var router: SampleRouterInterface?
// omitted the rest for simplicity
}
class SampleRouter: SampleRouterInterface {
var viewController: UIViewController?
// omitted the rest for simplicity
}
실제로 두 개의 참조 순환이 있습니다.
- Interactor->Presenter->ViewController->Interactor
- Interactor->Presenter->Router->ViewController->Interactor
이를 해결하기 위해 아래와 같이 약한 참조를 사용할 수 있습니다.
그러면 다음 다이어그램에 따라 더 이상 VIP에 대한 참조 순환이 없습니다.
블록 캡처 관련 참조 순환
후! 방금 두 개의 참조 순환을 수정했기 때문에 기분이 좋지만 아직 완료되지 않았습니다. 지금 앱을 실행하면 여전히 메모리 누수가 있음을 알 수 있습니다. 원인은 코드의 다음 부분입니다.
class CustomButton: UIView {
var buttonClickHander: (() -> Void)?
// omitted the rest for simplicity
}
class SampleViewController: UIViewController, SampleViewControllerInterface {
private lazy var customButton: CustomButton = {
let button = CustomButton()
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
private func setUpUI() {
view.addSubview(customButton)
customButton.buttonClickHander = {
self.interactor?.customButtonClicked()
}
// ...
}
}
문제가 있는 위치를 알게 되면 수정은 간단합니다. 아래를 참조하십시오.
요약
요약하면 여러 개체 내에서 발생하는 두 가지 유형의 참조 순환을 다루었습니다. 여기에서 데모 프로젝트를 찾을 수 있으며 수정 사항은 쉽게 검토할 수 있도록 풀 리퀘스트 에 준비되어 있습니다 . 이 기사가 참조 순환을 더 잘 이해하고 참조 순환을 피하는 데 도움이 되기를 바랍니다.

![연결된 목록이란 무엇입니까? [1 부]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































