8

What happens to your “fromView” after you use UIView.transitionFromView? How do you get it back? (re-initialize it?).

Here’s a simple example I made and get “fatal error: unexpectedly found nil while unwrapping an Optional value” when I try to get back to the “fromView” or reference a label on it, etc.

Let’s say I’ve set these views in my storyboard - I added a subview to the root called “cardView” and then 2 views under cardView called “backView” and “frontView"

Linked these up to the view controller and linked the Flip button to an action that looks like this (along with the variables):

@IBOutlet weak var backView: UIView!
@IBOutlet weak var frontView: UIView!
@IBOutlet var cardView: UIView!

var front = true

@IBAction func flipIt(sender: AnyObject) {
    if front {
        UIView.transitionFromView(self.frontView, toView: self.backView, duration: 1, options: UIViewAnimationOptions.TransitionFlipFromRight, completion: nil)
    } else {
        UIView.transitionFromView(self.backView, toView: self.frontView, duration: 1, options: UIViewAnimationOptions.TransitionFlipFromLeft, completion: nil)
    }
    front = !front
}

So when I run this - the first tap of the “Flip” button does fine, it flips over to the backView, but then when I tap it again I get “fatal error: unexpectedly found nil while unwrapping an Optional value” on the 2nd transitionFromView line (the one under “else”).

Obviously there’s some effect of transitionFromView that I don’t understand. I've tried a lot of different things, including a tutorial that uses this transition and was able to get it working but it doesn’t use the storyboard so I’m not sure how to apply how that tut does it to my storyboard views, apparently...

thanks for any help.

Tommy Draughn
  • 179
  • 1
  • 12

1 Answers1

10

You've declared your view properties as weak, so they're getting released as soon as it appears they're no longer needed. Just change them to strong (by removing "weak") and you should be golden:

@IBOutlet var backView: UIView!
@IBOutlet var frontView: UIView!
Dave Batton
  • 8,795
  • 1
  • 46
  • 50
  • Awesome Dave - thanks so much - that works. Can I give you bonus points for telling me why I lose my constraints on the labels on the subviews? After deleting "weak" this is flipping back and forth but the labels appear in the wrong position after tapping "Flip" from the first time. I guess I should be going to see if there's a place these constraints are set to weak...? yea I'm a newb... – Tommy Draughn May 17 '15 at 21:09
  • It doesn't seem like this flip should mess with the label constraints. Are you creating the constraints in code or Interface Builder? If in IB, they should be fine. But you could make them weak if they're created in the code, perhaps. – Dave Batton May 17 '15 at 21:14
  • Also, generally weak @IBOutlets is the way to go. It's only if you remove the view from the view hierarchy (which you're doing here) that you need strong properties. – Dave Batton May 17 '15 at 21:15
  • I did them in IB but I used "Reset to suggested" on all views so maybe it's a problem with that not being perfect - I only used it since this is only a test. Works fine on the initial view load though...but I'll go back and do these manually and see if for some reason it's a reason with those auto-constraints - brb. – Tommy Draughn May 17 '15 at 21:17
  • Wow, I don't understand it...after removing all constraints, putting them manually (or what I call manually - using IB but adjusting "first item" etc one at a time - going back through and double-checking them - it still comes out kinda the same way. For some reason now (maybe this is a clue) I get through 2 "Flip" taps before the UI goes whack (rather than the previous 1 tap, what? lol (love programming though, such a interesting mystery)). – Tommy Draughn May 17 '15 at 21:51
  • Also another clue, I'm pretty sure by the way it's doing it these views (backView and frontView) are coming back as subviews of my rootView rather than cardView. I write that because while cardView size/location is x=30, y=30, width=100, and height = 100. It loads up and looks good, tap "flip" and that 100x100 square flips over to the back with the other color and other label just like I want. – Tommy Draughn May 17 '15 at 21:52
  • Third click though now and the flip animations happens over to blank white 100x100 square and I can see most (but not all) of my colored view with the label on it way up at the top left of the screen. Tap Flip again and the animation happens where it supposed to but the colored label stuck up in the top-left does change to the other color.... – Tommy Draughn May 17 '15 at 21:52
  • By the way, thanks for the advice about IBOutlets generally being weak - I did catch that. – Tommy Draughn May 17 '15 at 21:57
  • I'll ask in a new question - you fixed the crash for me - thanks again, Dave. – Tommy Draughn May 19 '15 at 13:32
  • 6
    I found the answer before asking a new question - I needed to use the option "UIViewAnimationOptions.ShowHideTransitionViews" which "When present, this key causes views to be hidden or shown (instead of removed or added) when performing a view transition." If anyone reads this and needs to know how to add more than one option in UIView.transitionFromView, just create variable like: `var animationOptions = UIViewAnimationOptions.TransitionFlipFromLeft | UIViewAnimationOptions.ShowHideTransitionViews` and then type that in for "options:" when you call .transitionFromView. – Tommy Draughn May 19 '15 at 16:36
  • 4
    Small note for Swift2, if you want to use 2 options you need this syntax: var animationOptions = [UIViewAnimationOptions.TransitionFlipFromLeft, UIViewAnimationOptions.ShowHideTransitionViews] – Bruno Tereso Oct 19 '15 at 14:45