我正在研究从这里开始的协调器模式,但由于可能存在内存泄漏,我不了解从控制器中的通用按钮中解散的更安全方法(“后退”按钮的机制可以)。
例如,我到达 ViewController2,做我的事情,然后点击一个按钮(除了导航栏中的后退按钮之外的任何人)如何正确关闭?经典有问题popViewController
吗?还是在“MyCoordinatorClass”中更好地实现这样的功能??deinit
似乎总是正确调用,但我不确定哪个更好。另外,我一直使用推送,但它也可以在当前模式下使用,有什么可能的问题吗?欢迎任何帮助或澄清
protocol testProtocol: class {
func didTest()
}
import UIKit
class ViewController2: UIViewController, StoryboardedProtocol {
weak var coordinator: MainCoordinator?
weak var delegate: testProtocol?
override func viewDidLoad() {
super.viewDidLoad()
}
#warning("how to dismiss in a Coordinator pattern?")
@IBAction func myDelegteButtonTapped(_ sender: Any) {
//better this?
//navigationController?.popViewController(animated: true)
//or this?
//coordinator?.didTapFish()
delegate?.didTest()
}
deinit {
print("deallocated")
}
}
我的协调员协议
protocol Coordinator_Protocol: AnyObject {
var childCoordinators: [Coordinator_Protocol] { get set }
var navigationController: UINavigationController { get set }
func start()
}
我的故事板协议
protocol Storyboarded {
static func instantiate(StoryBoardName: String) -> Self
}
extension Storyboarded where Self: UIViewController {
static func instantiate(StoryBoardName: String) -> Self {
let id = String(describing: self)
let storyBoard = UIStoryboard(name: StoryBoardName, bundle: .main)
return storyBoard.instantiateViewController(identifier: id) as! Self
}
}
我的 MainCoordinatorClass
enum StoyboardsNames: String {
case main = "Main"
case secondSB = "SecondStoryboard"
}
import UIKit
class MainCoordinator: NSObject, Coordinator_Protocol, UINavigationControllerDelegate {
var childCoordinators = [Coordinator_Protocol]()
var navigationController: UINavigationController
init(navigationController: UINavigationController) {
self.navigationController = navigationController
}
func start() {
navigationController.delegate = self //passo 2
let vc = ViewController.instantiate(StoryBoardName: StoyboardsNames.main.rawValue)
vc.coordinator = self
navigationController.pushViewController(vc, animated: false)
}
func gotoViewController2(delegate: testProtocol?) {
let vc = ViewController2.instantiate(StoryBoardName: StoyboardsNames.main.rawValue)
vc.delegate = delegate
vc.coordinator = self
navigationController.pushViewController(vc, animated: true)
}
//MARK: - ordinary storyboard, this is my standard way.
func createAccount(messageForTest: String?) {
let vc = CreateAccountViewController.instantiate(StoryBoardName: StoyboardsNames.main.rawValue)
vc.message = messageForTest
vc.coordinator = self
navigationController.pushViewController(vc, animated: true)
// navigationController.present(vc, animated: true, completion: nil)
}
func didTapFish() {
navigationController.popViewController(animated: true)
}
func didRequestCancel() {
navigationController.popToRootViewController(animated: true)
}
//intercepts "back button" from navigation bar
func childDidiFinish(_ child: Coordinator_Protocol?) {
for (index, coordinator) in childCoordinators.enumerated() {
if coordinator === child {
childCoordinators.remove(at: index)
print("removed buying from coordinators")
break
}
}
}
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 buyViewController = fromViewController as? BuyViewController {
print("fai cose in caso di BuyViewController")
childDidiFinish(buyViewController.coordinator)
}
}
}