ios7autolayoutuikit-dynamicsuicollisionbehavioruidynamicbehavior

UIDynamics and Device Rotation


If I add any kind of UIDynamicBehavior to my views, it completely breaks things when the device is rotated. Here's what it is in portrait (displaying correctly):

Correct Layout

And here it is in landscape, all broke:Broken layout

I don't believe it's an autolayout issue because if I remove the calls to add the UIDynamicBehavior it works fine with no autolayout problems. No autolayout errors are ever thrown either. Here's the code:

@interface SWViewController () {
  UICollisionBehavior *coll;
  UIDynamicAnimator *dynamicAnimator;
}

@implementation SWViewController
- (void)viewDidLoad {
  [super viewDidLoad];
  dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
}

- (void)viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];
  [self setupCollisions]; // commenting this out fixes the layout
}

- (void)setupCollisions {
  NSArray *dynamicViews = @[greenView];
  coll = [[UICollisionBehavior alloc] initWithItems:dynamicViews];    
  CGFloat topBound = CGRectGetMinY(greenView.frame);
  [coll addBoundaryWithIdentifier:@"top"
                        fromPoint:CGPointMake(0, h1)
                          toPoint:CGPointMake(CGRectGetWidth(greenView.frame), h1)];    
  [dynamicAnimator addBehavior:coll];
}

If I override didRotateFromInterfaceOrientation I can see that the top boundary of greenView doesn't follow what autolayout says it should (again, removing the call to setupCollisions fixes this).

The autolayout boundaries on greenView are:

height = 200
trailing space to Superview = 0
leading space to Superview = 0
bottom space to Superview = 0

Solution

  • One solution I found was to override willRotateToInterfaceOrientation: and remove the UIDynamicItems and then re-add them in didRotateFromInterfaceOrientation:. This strikes me as rather hacky, and could potentially introduce bugs once I add more complex behaviors.