Почему слабые делегаты не нужны при использовании файлов .xib?
Я сделал простой проект, в котором не используются раскадровки. Он просто использует .xib файлы, связанные с UIViewControllers. Он предоставляет пользователю кнопку, которая при нажатии выдвигает новый контроллер вида и позволяет ему go назад. Если приведенный ниже navDelegate указан как слабый, то навигация к DetailViewController никогда не происходит, поскольку navDelegate всегда будет иметь значение nil.
SceneDelegate.swift
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let winScene = scene as? UIWindowScene else {
return
}
window = UIWindow(windowScene: winScene)
AppCoordinator().start()
}
}
AppCoordinator.swift
import UIKit
protocol Coordinator: AnyObject {
func start()
}
class AppCoordinator: Coordinator {
let router = UINavigationController()
func start() {
let vc = RootViewController()
vc.navDelegate = self
router.viewControllers = [vc]
let window = UIApplication.shared.windows.first
window?.rootViewController = router
window?.makeKeyAndVisible()
}
}
extension AppCoordinator: NavDelegate {
func buttonTapped() {
let vc = DetailViewController()
router.pushViewController(vc, animated: true)
}
}
RootViewController.swift
import UIKit
protocol NavDelegate: AnyObject {
func buttonTapped()
}
class RootViewController: UIViewController {
// Does this navDelegate need to be weak when using .xib files?
var navDelegate: NavDelegate?
init() {
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func tapDetailButton(_ sender: Any) {
// Always prints 2 no matter how many times I navigate back and forth
let refCount = CFGetRetainCount(navDelegate)
print("Ref Count: \(refCount)")
navDelegate?.buttonTapped()
}
}
DetailViewController.swift
import UIKit
class DetailViewController: UIViewController {
init() {
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Итак, при дальнейшем понимании @matt кажется, что если у вас есть AppCoordinator в качестве переменной экземпляра SceneDelegate тогда наличие navDelegate как слабого работает. Я полагаю, ошибка в том, что называет navDelegate делегатом. Его нужно просто назвать чем-то вроде navHelper, чтобы не было путаницы в том, слаб он или нет.