Слабые делегаты и файлы .xib - PullRequest
0 голосов
/ 26 апреля 2020

Почему слабые делегаты не нужны при использовании файлов .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, чтобы не было путаницы в том, слаб он или нет.

1 Ответ

0 голосов
/ 26 апреля 2020

Ничего общего с XIBS. Или делегаты, на самом деле.

Если вы знаете, что означает weak, вы знаете, что это означает: «Если никто больше не имеет строгой ссылки на эту вещь, пусть она go исчезнет».

Поэтому, когда вы говорите vc.navDelegate = self, где self в экземпляре AppCoordinator, то, если никакая другая ссылка на этот экземпляр AppCoordinator не сохраняет его, он сразу же исчезает в клубе дыма.

Ну, какова история жизни этого экземпляра?

 AppCoordinator().start()

Что делает эта линия? Он создает экземпляр AppCoordinator, вызывает на нем start, а затем сбрасывает AppCoordinator на этаже, позволяя ему go прекратить существование, если никто не удерживает его. И никто другой не держится за него, потому что единственное упоминание, которое кто-либо еще имел к нему, было weak.

...