因为这个问题,我头疼。为什么我的 SplashscreenViewController 没有取消初始化?你们在下面发布的代码中看到任何潜在的保留周期吗? 我试图检查 Malloc 堆栈,但找不到任何有用的信息。
final class SplashscreenViewController: UIViewController {
var viewModel: SplashscreenViewModelType!
private let animationStartScale: CGFloat = 0.75
private let animationEndScale: CGFloat = 1.0
private let animationDuration: TimeInterval = 0.4
private let splashscreenDuration: TimeInterval = 1.5
@IBOutlet private weak var logoImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
animateLogo(scale: animationStartScale)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
DispatchQueue.main.asyncAfter(deadline: .now() + splashscreenDuration, execute: { [weak self] in
self?.viewModel.onFinish.onNext(())
})
}
private func animateLogo(scale: CGFloat) {
UIView.animate(withDuration: animationDuration, animations: {
self.transformImage(scale: scale)
}, completion: { _ in
if scale == self.animationStartScale {
self.animateLogo(scale: self.animationEndScale)
} else {
self.animateLogo(scale: self.animationStartScale)
}
})
}
private func transformImage(scale: CGFloat) {
logoImageView.transform = CGAffineTransform(scaleX: scale, y: scale)
}
}
保存 SplaschreenViewController 实例的类是其协调器。下面的代码:
final class SplashscreenCoordinator: BaseCoordinator {
private let window: UIWindow
init(window: UIWindow) {
self.window = window
}
override func start() -> Observable<Void> {
let vc: SplashscreenViewController = SwinjectStoryboard.instantiateInitialViewController()
window.rootViewController = vc
window.makeKeyAndVisible()
let onFinish = vc.viewModel.onFinish
.asObservable()
.flatMap { [unowned self] _ -> Observable<Void> in
guard self.window.rootViewController == vc else {
return Observable<Void>.empty()
}
if UserPreferencesManager.isLoggedIn() {
return self.startAppForLoggedInUser()
} else {
return self.startAppForAnonymousUser()
}
}
return onFinish
}
private func startAppForLoggedInUser() -> Observable<Void> {
let tabBar = TabBarCoordinator(window: window)
return coordinate(to: tabBar)
}
private func startAppForAnonymousUser() -> Observable<Void> {
let startCoordinator = StartCoordinator(window: window)
return coordinate(to: startCoordinator)
}
}
以及来自 BaseCoordinator 的一些代码:
...
private func store(coordinator: BaseCoordinator) {
childCoordinators[coordinator.identifier] = coordinator
}
private func free(coordinator: BaseCoordinator) {
childCoordinators[coordinator.identifier] = nil
}
func coordinate(to coordinator: BaseCoordinator) -> Observable<Void> {
store(coordinator: coordinator)
return coordinator.start()
.do(onNext: { [weak self] _ in
self?.free(coordinator: coordinator)
})
}
...
提前感谢您的回答!
我可以看到如何防止SplashscreenViewController
解除分配的两种方法如下:
- 如果未解除分配作为其
rootViewController
的window
。请记住,应用程序会保留密钥窗口。 - 在
start()
函数中,Observable
闭包保留vc
变量。此Observable
可以显式保留在其他地方或DisposeBag
中。