Reputation: 2193
My initial GameViewController
has a delegate property of a GameDelegate
. I'm setting this property in the 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.
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.
Upvotes: 0
Views: 381
Reputation: 1761
Safe approach is using weak delegate. If you handle nil then it shouldn't be a problem.
weak var delegate: GameDelegate?
var gameScore: GameScore? {
return delegate?.gameScore
}
Do you intent on calling 'delegate' when 'gameScore' changes? If you want to save 'gameScore' and as well as return 'delegate' then you should use property observer.
var gameScore: GameScore {
didSet {
delegate?.gameScore
}
}
Upvotes: 1
Reputation: 9352
The problem is that you are declaring the gameTracker
in a function, rather than as a class-level variable. The AppDelegate
's reference to it is released immediately when the function exits, leaving your GameViewController
with the only reference to it.
The way to solve this is to declare gameTracker
as a class-level variable in your AppDelegate
:
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 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
.
Upvotes: 2