Skip to content

Instantly share code, notes, and snippets.

@devxoul
Last active October 16, 2019 13:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devxoul/a376db02653ccff732d365636d486f03 to your computer and use it in GitHub Desktop.
Save devxoul/a376db02653ccff732d365636d486f03 to your computer and use it in GitHub Desktop.
Does UIViewController get deallocated synchronously? NO. (if view is loaded)
weak var weakViewController: UIViewController?
_ = {
let viewController = UIViewController()
viewController.loadViewIfNeeded() // this line prevents from deallocation
weakViewController = viewController
}()
XCTAssertNil(weakViewController) // (fail) weakViewController = Optional(<UIViewController: 0x7fd55e705080>)
DispatchQueue.main.async {
print(weakViewController) // nil
}
@oozoofrog
Copy link

UIViewController.loadViewIfNeeded() -> .loadViewIfRequired() -> .loadView() -> .defaultInitialViewFrame() -> ._window -> ._rootAncestorViewController -> .nonModalAncestorViewControllerStopAtIsPresentationContext( flag: Bool) -> Self(UIViewController) 로 진행하면서 마지막 _nonModal...에서 자기자신(UIViewController)를 반환하며 현재의 오토릴리즈 풀에 등록시키는 것이 원인이었네요.

결국 SwiftUI방에서 원숭이님이 autorelease풀을 별도로 사용하신게 정답이었군요.

@oozoofrog
Copy link

심플하게 테스트 해보려면 loadView...를 사용할 필요없이 performSelector를 통해 직접 _nonModalAncestorViewControllerStopAtIsPresentationContext: 를 호출하면 되는데, swift에서는 perform selector를 사용하는 과정에서 autorelease풀에 등록이 되어버리니 테스트 케이스를 objective c로 생성하고 나서야 명확하게 이유를 살펴볼 수 있었습니다.

@oozoofrog
Copy link

oozoofrog commented Oct 16, 2019

arc 에서의 autorelease 최적화와 관련한 이슈라고 생각합니다. 같은 문제를 일으키는 좀 더 간단한 구현체를 만들어보는 중이네요. (아니면 -fno-objc-arc 플래그로 컴파일을 해봐야하나 .. 고민)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment