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

Using strong delegate for initial ViewController in AppDelegate

我的初始 GameViewController 有一个 GameDelegate 的代表 属性。我在 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
}

这只适用于我的代表很强:

class GameViewController: UIViewController{

        var delegate: GameDelegate?

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

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

使用弱委托会导致应用程序崩溃,因为在 GameViewController 出现后委托将为 nil。

我的问题是:这种方法安全吗?如果不安全,应该怎么做?我读过有关代表的信息,建议将其保留为弱变量以防止保留周期。我没有使用故事板。

安全方法是使用弱委托。如果你处理 nil 那么它应该不是问题。

weak var delegate: GameDelegate?

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

您打算在 'gameScore' 更改时调用 'delegate' 吗?如果你想保存 'gameScore' 以及 return 'delegate' 那么你应该使用 属性 观察者。

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

问题是您在函数中声明 gameTracker,而不是作为 class 级变量。 AppDelegate 对它的引用会在函数退出时立即释放,留下你的 GameViewController 对它的唯一引用。

解决这个问题的方法是在 AppDelegate:

中将 gameTracker 声明为 class 级变量
var gameTracker: GameTracker?

您需要将其声明为可选,因为您只想在满足 if 条件时实例化它:

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

如果这样做,您将能够在 GameViewController 中将 delegate 声明为 weak