2

I'm trying to lazy instantiate a UIDynamicAnimator in my code. I want to initialise it with an UIView as an IBOutlet I have.

class ViewController: UIViewController {

     @IBOutlet var gameView : UIView

     @lazy var animator = UIDynamicAnimator(referenceView: gameView)
...

I'm assuming this isn't working because the UIView isn't yet created because the animator property throws back an error saying it can't find the gameView.

How can I get around this?

Sawyer05
  • 1,604
  • 2
  • 22
  • 37

2 Answers2

3

In the session video "Building Interruptible and Responsive Interactions", they did exactly this.

The solution is to define animator as an Optional and initialize it inside viewDidLoad.

class ViewController: UIViewController {
    var animator : UIDynamicAnimator?
    @IBOutlet var gameView : UIView
    override func viewDidLoad() {
       super.viewDidLoad()
       animator = UIDynamicAnimator(referenceView: gameView)
       animator!.property = value
       ...
    }
...

I slightly dislike this because future references to animator will all need to unwrap it.

A slightly better approach imo is to define it as an implicitly unwrapped optional. So it would look like this:

class ViewController: UIViewController {
    var animator : UIDynamicAnimator!
    @IBOutlet var gameView : UIView
    override func viewDidLoad() {
       super.viewDidLoad()
       animator = UIDynamicAnimator(referenceView: gameView)
       animator.property = value
       ...
    }
...
Jack
  • 16,677
  • 8
  • 47
  • 51
  • Thanks Jack, hadn't thought of declaring it as an optional. Found the session video you talked about so I will look through that too. thanks for the help – Sawyer05 Jun 19 '14 at 12:41
  • Another quick question..Does this mean things I would set in the lazy instantiation method should be set in the viewDidLoad instead? say for instance a Gravity.magnitude property? – Sawyer05 Jun 19 '14 at 12:47
  • 2
    @Sawyer05 sadly yes, everything needs to go there. I do hope they introduce a clean way of doing this in the future. – Jack Jun 19 '14 at 12:48
0

Use a closure:

lazy private var dynamo: UIDynamicAnimator = {
        return UIDynamicAnimator(referenceView: self.view)
    }()

"Lazy" means it won't be initialized until first use.

The closure has access to self.view (or whatever other local view you want to use,) but it doesn't try to read it until the first read of "dynamo" happens.

I like this as a combination of clean and safe.

mmaclaurin
  • 1,412
  • 1
  • 13
  • 18