我使用协调器模式和子协调器来提供松散耦合的代码,并且符合单一责任原则。为了处理向后导航,我决定使用导航控制器委托(相应地,本文使用https://www.hackingwithswift.com/articles/175/advanced-coordinator-pattern-tutorial-ios)。但我的问题是,我有家庭VC和家庭协调员,接下来我去锻炼VC与锻炼协调员,然后我去锻炼VC与锻炼协调员。
所以我想有一个锻炼协调员和锻炼协调员作为孩子的家庭协调员。

看起来一切正常,但是我的锻炼协调器和锻炼协调器之间有一个内存泄漏,因为我不能删除锻炼协调器后,我使用后退按钮导航。我的导航控制器委托不能识别我何时返回。
class HomeCoordinator: NSObject, Coordinator, UINavigationControllerDelegate {
var childCoordinators = [Coordinator]()
var navigationController: UINavigationController
init(navigationController: UINavigationController) {
self.navigationController = navigationController
navigationController.navigationBar.prefersLargeTitles = true
navigationController.navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.foregroundColor : UIColor.white]
}
func start() {
navigationController.delegate = self
let vc = HomeFactory.makeHomeScene(delegate: self)
navigationController.pushViewController(vc, animated: false)
}
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
guard let fromViewController = navigationController.transitionCoordinator?.viewController(forKey: .from) else { return }
if navigationController.viewControllers.contains(fromViewController) {
return
}
if let addWorkoutViewController = fromViewController as? NewWorkoutViewController {
let workoutCoordinator = addWorkoutViewController.presenter?.workoutCoordinatorDelegate
childDidFinish(workoutCoordinator)
}
}
}
extension HomeCoordinator: HomeCoordinatorDelegate {
func goToWorkoutCreating() {
let child = AddWorkoutCoordinator(navigationController: navigationController)
child.passWorkoutToHomeDelegate = self
childCoordinators.append(child)
child.parentCoordinator = self
child.start()
}
}
class AddWorkoutCoordinator: NSObject, Coordinator, UINavigationControllerDelegate {
var parentCoordinator: Coordinator?
var exerciseNumber: Int?
weak var passWorkoutToHomeDelegate: PassWorkoutToHome?
var childCoordinators = [Coordinator]()
var navigationController: UINavigationController
init(navigationController: UINavigationController) {
self.navigationController = navigationController
navigationController.navigationBar.tintColor = .white
}
func start() {
let vc = AddWorkoutFactory.makeAddWorkoutScene(delegate: self)
navigationController.pushViewController(vc, animated: true)
}
func childDidFinish(_ child: Coordinator?) {
for (index, coordinator) in childCoordinators.enumerated() {
if coordinator === child {
childCoordinators.remove(at: index)
break
}
}
}
// THIS FUNCTION IS NOT RESPOND AT ALL, BUT IT RESPONDS IN HOME COORDINATOR
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
guard let fromViewController = navigationController.transitionCoordinator?.viewController(forKey: .from) else { return }
if navigationController.viewControllers.contains(fromViewController) {
return
}
if let newExerciseViewController = fromViewController as? NewExerciseViewController {
// childDidFinish(newExerciseViewController.presenter?.exerciseCoordinatorDelegate)
// childDidFinish(newExerciseViewController.presenter!.exerciseCoordinatorDelegate)
}
}
}
extension AddWorkoutCoordinator: AddWorkoutCoordinatorDelegate {
func goToAddExercise() {
let child = AddExerciseCoordinator(navigationController: navigationController)
child.passExerciseToWorkoutDelegate = self
childCoordinators.append(child)
child.start()
}
class AddExerciseCoordinator: NSObject, Coordinator {
weak var passExerciseToWorkoutDelegate: PassExerciseToWorkoutDelegate?
var childCoordinators = [Coordinator]()
var navigationController: UINavigationController
init(navigationController: UINavigationController) {
self.navigationController = navigationController
self.navigationController.navigationBar.tintColor = .white
}
func start() {
let vc = AddExerciseFactory.makeAddExerciseScene(delegate: self)
navigationController.pushViewController(vc, animated: true)
}
func startEditExercise(setData: [ExerciseFieldsModel], exerciseName: String) {
let vc = AddExerciseFactory.makeAddExerciseScene(delegate: self)
vc.presenter?.textFieldsModel = setData
vc.exerciseText = exerciseName
navigationController.pushViewController(vc, animated: true)
}
}
extension AddExerciseCoordinator: NewExerciseCoordinatorDelegate {
func saveExercise(newExercise: ExerciseCellInNewWorkout) {
navigationController.popViewController(animated: true)
passExerciseToWorkoutDelegate?.passExerciseToWorkout(exercise: newExercise)
}
}所以基本上的问题是,使用导航控制器委托didShow方法,我需要获取"fromViewController“的类型,所以如果我有一个像锻炼协调器这样的孩子,一切都好,我不能轻易地删除它,但当我有一个更深的层,所以我有锻炼协调器,在那之后,我不知道如何使用导航控制器委托didShow方法来识别是否弹出锻炼协调器。因此,我尝试在锻炼协调器中使用导航控制器didShow,但正如我在代码注释中所写的那样,它根本没有响应。
你能帮我得到一些关于如何检测用户是否在练习VC上点击后退按钮的建议吗?也许我的想法不好,只有锻炼协调者应该是孩子,而锻炼协调者不应该是。
发布于 2021-09-09 11:20:48
当您的ExerciseViewController超出作用域(被删除)时,它应该通知在导航控制器上推送它的对象。看起来那是你的ExerciseCoordinator。
按照设置UIKit的视图包含系统的方式设置您的协调器包含系统。其中协调器具有addChild(coordinator:)方法和removeFromParent()方法。当视图控制器通知协调器它超出了作用域时,协调器应该调用它的removeFromParent()方法。
上面的系统比依赖于didShow要好得多,并且适用于任何一种表示方法。
https://stackoverflow.com/questions/69116862
复制相似问题