【问题标题】:Using strong delegate for initial ViewController in AppDelegate在 AppDelegate 中为初始 ViewController 使用强委托
【发布时间】:2017-05-19 11:58:18
【问题描述】:

我最初的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 后委托将为零。

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

【问题讨论】:

    标签: ios swift delegates automatic-ref-counting


    【解决方案1】:

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

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

    当“gameScore”发生变化时,您是否打算调用“delegate”?如果你想保存 'gameScore' 并返回 'delegate' 那么你应该使用属性观察者。

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

    【讨论】:

    • 是的,这就是我使用强代表而不是弱代表的确切原因。计算出来的属性需要调用委托。
    【解决方案2】:

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

    解决此问题的方法是将gameTracker 声明为AppDelegate 中的类级变量:

    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

    【讨论】:

    • 很好的解释,这是有道理的,因为我确实计算了来自 ARC 的 2 个引用。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-15
    • 2012-01-16
    • 2013-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多