弱委托和 .xib 文件

Posted

技术标签:

【中文标题】弱委托和 .xib 文件【英文标题】:Weak delegates and .xib files 【发布时间】:2020-04-26 18:55:52 【问题描述】:

为什么在使用 .xib 文件时不需要弱委托?

我做了一个不使用故事板的简单项目。它只使用与 UIViewControllers 关联的 .xib 文件。它向用户展示了一个按钮,当按下该按钮时,它会推动一个新的视图控制器并允许他们返回。如果下面的 navDelegate 被列为弱,则导航到 DetailViewController 永远不会发生,因为 navDelegate 将始终为零。

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 的东西,这样就不会混淆它是否应该是弱的。

【问题讨论】:

CFGetRetainCount 给你的信息一点用处都没有。不计算引用,检查是否存在所有权周期。谁拥有(强烈引用)实例? @Sulthan 有没有办法通过 xcode 做到这一点?我查看了内存图调试,没有发现泄漏问题或所有权周期。 【参考方案1】:

与xibs无关。或者委托,真的。

如果您知道weak 的含义,您就知道它的意思是“如果没有其他人强烈提及这件事,那就让它不复存在。”

因此,当您在 AppCoordinator 实例中说 vc.navDelegate = self,其中 self 时,如果没有其他对此 AppCoordinator 实例的引用保留它,它会立即消失在烟雾中。

那么,这个实例的故事是什么?

 AppCoordinator().start()

那条线是做什么的?它创建一个 AppCoordinator 实例,在其上调用 start,然后将 AppCoordinator 放到地板上,如果没有其他人抓住它,就让它消失。并且没有其他人 坚持使用它,因为其他人对它的唯一引用是 weak

【讨论】:

好的。因此,当 AppCoordinator 是 SceneDelegate 的实例变量时,引用计数从 2 上升到 3,但无论我来回导航多少次,它始终为 3。此外,当我将 AppCoordinator 声明为 SceneDelegate 的实例变量并在 RootViewController 导航中将 navDelegate 声明为弱并且引用计数为 2 时。所以我想我要问的问题是声明一个弱的委托仅在它被持有时是必需的另一个类作为实例变量。 @BobDave 所有委托都由另一个类作为实例变量持有。这就是代表的目的。 @Sulthan。我说的是实现委托的类。当它被另一个类持有时与当它只是在一个函数中使用时。 不要使用引用计数。只是关于所有权的事情。如果没有人拥有一件物品,它就会不复存在。好吧,如果一个对象的唯一持久引用是weak,那么没有人拥有它,所以... 也回答您的问题:这里的问题是您使用了错误的词。此对象不是委托。委托的意思是:“对于这个功能,我愿意让步给已经存在的其他对象,用于其他目的,但可能想做这项工作。”你不是在做委托,而是在做依赖注入。您正在给一个对象一个辅助对象它拥有

以上是关于弱委托和 .xib 文件的主要内容,如果未能解决你的问题,请参考以下文章

为 .xib 所有者的 ViewController 中的 textField 设置委托

XIB 和视图控制器之间的协议委托

弱引用委托未恢复

为啥使用弱指针进行委托?

Swift 委托 - 何时在委托上使用弱指针

如何在 xcode 4.5 中选择数据源和委托?