If you remove these two lines
view.layer.anchorPoint = CGPointMake(locationInView.x / view.bounds.size.width, locationInView.y / view.bounds.size.height);
view.center = locationInSuperview;
Then your view panning behaves as you would expect. Why are you changing the layer's anchorpoint anyway? IN general your code seems over-complicated for what you are trying to achieve. See David Rönnqvist, understanding the anchor point as to how changing the anchorpoint has (often unintended) implications for the view's frame property.
Moreover, it is usually a good idea to leave the top-level view alone (the view controller's self.view
) and manipulate subviews. That way you know how everything relates to the viewController's view without wondering what is going on with respect to the UIWindow. When you rotate the device, a rotation transform is applied to that top-level view, which doesn't help when you are inspecting frame data. It's subviews' properties aren't affected by that transform.
Your code behaves as you expect it to in untransformed portrait mode, and only throws up strange results when in landscape or portrait-upsidedown. These are the cases where the view has had a rotational transform applied. Apple says that the frame's origin property is undefined when a transform has been applied to the view, so when you do this:
self.view.frame = self.view.frame
you are assigning a property in an undefined state. Expect the unexpected.
You could change your viewloading code thus:
- (void)viewDidLoad
{
[super viewDidLoad];
UIView* subview = [[UIView alloc] initWithFrame:
CGRectMake(0, 0
, self.view.bounds.size.width
, self.view.bounds.size.height)];
[self.view addSubview:subview];
subview.backgroundColor = UIColor.redColor;
[subview setAutoresizingMask:UIViewAutoresizingFlexibleWidth
|UIViewAutoresizingFlexibleHeight];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]
initWithTarget:self
action:@selector(onPan:)];
pan.maximumNumberOfTouches = 1;
[subview addGestureRecognizer:pan];
}
Here we do not override -loadView, leave that alone to create the top-level view automatically, then we implement a subview in viewDidLoad
instead. Now your test app behaves correctly.