Rotating an UIView using UIDynamics and gravity from CMMotionManager

680 views Asked by At

I have an UIView which is a picture frame hanging on a nail from a string. I'm trying to rotate the view around its anchorPoint to keep the view's bottom flat(parallel with the ground) regardless of the devices rotation. I'm trying to achieve this by using CMMotionManager and UIDynamics and can't seem to get anything working properly today. Here's some code...

- (void)viewDidLoad
{
[super viewDidLoad];

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

CGRect pictureFrameBounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(self.view.bounds)/2.5f, CGRectGetHeight(self.view.bounds)/5);
UIView *pictureFrame = [[UIView alloc] initWithFrame:pictureFrameBounds];
[pictureFrame setBackgroundColor:[UIColor redColor]];
[self.view addSubview:pictureFrame];

self.gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[pictureFrame]];

self.collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[pictureFrame]];
[self.collisionBehavior setTranslatesReferenceBoundsIntoBoundary:YES];
[self.animator addBehavior:self.collisionBehavior];

CGPoint anchorPoint = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetHeight(self.view.bounds)/8);
self.attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:pictureFrame
                                                    offsetFromCenter:UIOffsetMake(0.0f, -CGRectGetHeight(pictureFrame.bounds)/2.5f)
                                                    attachedToAnchor:anchorPoint];
[self.attachmentBehavior setDamping:0];
[self.attachmentBehavior setLength:0];
[self.attachmentBehavior setFrequency:0];
[self.animator addBehavior:self.attachmentBehavior];

UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[pictureFrame]];
[itemBehavior setAllowsRotation:YES];
[self.animator addBehavior:itemBehavior];

NSOperationQueue* motionQueue = [NSOperationQueue new];

 self.motionManager = [[CMMotionManager alloc] init];
[self.motionManager startDeviceMotionUpdatesToQueue:motionQueue
                                        withHandler:^(CMDeviceMotion *motion, NSError *error) {
                                           [self.gravityBehavior setGravityDirection:CGVectorMake(motion.gravity.x, motion.gravity.y)];
                                        }];
}

I've tried motion.gravity.x as an angularForce on itemBehavior to verify the forces are returning correctly, and the view rotates the correct direction, which everything seems to be fine. The problem with this approach is that the view continues to rotate since theres constant force being applied. Using setGravityDirection: results with the view anchored with no rotation. Some help would be much appreciated! thanks!

1

There are 1 answers

0
Woschwe On

try to change the NSOperationQueue to the mainQueue. This helped me.

[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
[self.gravityBehavior setGravityDirection:CGVectorMake(motion.gravity.x, -(motion.gravity.y))];
}];

Hope this helped you too.