[iOS] 순환 참조

Han's·2023년 7월 10일
0

TIL

목록 보기
1/20
post-thumbnail
post-custom-banner

아래의 코드에서 PlannerDetailViewController은 왜 메모리에서 해제되지 않을까? 🤔

final class PlannerDetailViewController: UIViewController {
    
    var date: Date?
    var reloadCalendar: ((_ relodaCalendar: Bool) -> Void)?
    private let viewModel = TodoManager()
    private var subscriptions = Set<AnyCancellable>()
    
    private lazy var addTodoButton: UIButton = {
        let button = UIButton(type: .system)
        button.setImage(UIImage(systemName: "plus.circle"), for: .normal)
        button.addTarget(self, action: #selector(didTappedAddTodoButton), for: .touchUpInside)
        button.isEnabled = false
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        bind()
    }
    
    deinit {
        print("deinit - PlannerDetailVC")
    }
}

private extension PlannerDetailViewController {
    func bind() {
        inputTodoTextField.textFieldPublisher
            .receive(on: DispatchQueue.main)
            .sink { text in
                self.addTodoButton.isEnabled = !text.isEmpty
            }
            .store(in: &subscriptions)
    }
}

Set<AnyCancellable>()을 사용하면 알아서 구독을 해제해 준다는 것을 믿고 클로저 내에서 약한 참조를 사용하지 않았다... 문제를 해결하기 위해 약한 참조 또는 미소유 참조를 사용해야 한다.

func bind() {
        inputTodoTextField.textFieldPublisher
            .receive(on: DispatchQueue.main)
            .sink { [weak self] text in
                self?.addTodoButton.isEnabled = !text.isEmpty
            }
            .store(in: &subscriptions)
    }

메모리 누수는 치명적이기 때문에 반드시 클로저를 사용할 때는 약한 참조, 미소유 참조를 사용하는 습관을 들어야 한다는 것을 다시 깨닫는 기회였다.

profile
🍎 iOS Developer
post-custom-banner

0개의 댓글