简体   繁体   English

在AppDelegate中为初始ViewController使用强委托

[英]Using strong delegate for initial ViewController in AppDelegate

My initial GameViewController has a delegate property of a GameDelegate . 我最初的GameViewController具有的委托属性GameDelegate I'm setting this property in the AppDelegate : 我在AppDelegate设置此属性:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.

    //Set initial view controller
    window = UIWindow(frame: UIScreen.main.bounds)
    if let window = window {
        let gameTracker = GameTracker()
        let gameViewController = GameViewController()
        gameViewController.delegate = gameTracker
        window.rootViewController = gameViewController
        window.makeKeyAndVisible()
    }
    return true
}

This only works since my delegate is strong: 这仅在我的代表很强时才起作用:

class GameViewController: UIViewController{

        var delegate: GameDelegate?

        var gameScore: GameScore {
            return (delegate!.gameScore)
        }

        override func viewDidLoad() {
            super.viewDidLoad()
        }
    }

Using a weak delegate will cause the App to crash since delegate will be nil after the GameViewController is presented. 使用弱的委托将导致应用程序崩溃,因为在呈现GameViewController之后委托将为零。

My question is: Is this approach safe, and if not, how should it be done? 我的问题是:这种方法安全吗?如果不安全,应该怎么做? I've read about delegates and it's recommend to keep it as a weak var to prevent a retain cycle. 我已经阅读了有关委托的内容,建议将其保留为弱变量,以防止保留周期。 I'm not using Storyboards. 我没有使用情节提要。

The problem is that you are declaring the gameTracker in a function, rather than as a class-level variable. 问题在于您是在函数中而不是在类级变量中声明gameTracker The AppDelegate 's reference to it is released immediately when the function exits, leaving your GameViewController with the only reference to it. 当函数退出时, AppDelegate对它的引用将立即释放,而GameViewController仅有其引用。

The way to solve this is to declare gameTracker as a class-level variable in your AppDelegate : 解决此问题的方法是在您的AppDelegate gameTracker声明为类级变量:

var gameTracker: GameTracker?

You need to declare it as an optional, since you only want to instantiate it when your if condition is met: 您需要将其声明为可选的,因为您只想在满足if条件时实例化它:

if let window = window {
    self.gameTracker = GameTracker()
    let gameViewController = GameViewController()
    gameViewController.delegate = self.gameTracker
    window.rootViewController = gameViewController
    window.makeKeyAndVisible()
}

If you do this, you will be able to declare your delegate as weak in your GameViewController . 如果执行此操作,则可以在GameViewController中将delegate声明为weak

Safe approach is using weak delegate. 安全的方法是使用弱委托。 If you handle nil then it shouldn't be a problem. 如果您处理nil,那应该不是问题。

weak var delegate: GameDelegate?

var gameScore: GameScore? {
    return delegate?.gameScore
}

Do you intent on calling 'delegate' when 'gameScore' changes? 您是否打算在'gameScore'更改时调用'delegate'? If you want to save 'gameScore' and as well as return 'delegate' then you should use property observer. 如果要保存“ gameScore”并返回“ delegate”,则应使用属性观察器。

var gameScore: GameScore {
    didSet {
        delegate?.gameScore
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM