title: Why is scaling/zooming-in an SKNode forcing the view into the left of the screen?
body: <p>I'm following Ray Wenderlich's 'iOS Games by Tutorials' &amp; I got everything in my world setup &amp; working: The entire game is in Landscape mode &amp; there's one SKNode called _worldNode &amp; everything, except _uiNode (in-game UI), is added to it. Player character walks to a touched location &amp; _worldNode moves under him like a treadmill. However, like all functionality (or as they call it: "juice") addicts I wanted to add zoom in/out functionality through UIPinchGestureRecognizer by scaling _worldNode, which I did. But now every time I zoom in, the "camera" moves to the bottom left. Zooming out moves the view to the top right of the screen. It's a mess. I need the view to stay centered on the player character &amp; I've tried everything I could come up with &amp; find online. The closest thing I came to was using the technique from <a href="https://stackoverflow.com/questions/21900614/sknode-scale-from-the-touched-point?lq=1">SKNode scale from the touched point</a> but I still get the bloody bottom left/top right mess. I realized this mess happens only when I update the camera/view (it's really _worldNode.position). Therefore, 'didSimulatePhysics' or 'didFinishUpdate' methods don't help. In fact, even a one time button that slightly moves/updates the camera view (_worldNode.position) still gives me the bottom left/top right problem. Here is my code. I hope someone can take a look &amp; tell me what to modify to get things working.</p>
  
  <pre><code>@interface GameScene () &lt;SKPhysicsContactDelegate, UIGestureRecognizerDelegate&gt;
  {
      UIPinchGestureRecognizer        *pinchGestureRecognizer;
  }
  </code></pre>
  
  <p>//Properties of my GameScene.  </p>
  
  <pre><code>@property SKNode        *worldNode;   
  @property etc. etc.
  
  
  //Called by -(id)initWithSize:(CGSize)size method &amp; creates the in-game world.
  -(void)createWorld
  {
      [_worldNode addChild:_backgroundLayer];
  
      [self addChild:_worldNode];
      self.anchorPoint        = CGPointMake(0.5, 0.5); //RW tutorial did it this way.
      _worldNode.position     = CGPointMake(-_backgroundLayer.layerSize.width/2, -_backgroundLayer.layerSize.height/2); //Center.
  
      //Then I add every node to _worldNode from this point on.
  }
  
  //Neccessary for gesture recognizers.
  -(void)didMoveToView:(SKView *)view
  {
      pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handleZoomFrom:)];
      [view addGestureRecognizer:pinchGestureRecognizer];
  }
  
  //"Camera" follows player character. 'didSimulatePhysics' doesn't help either.
  -(void)didFinishUpdate
  {
      //IF '_pinchingScreen' == YES then screen pinching is in progress. Thus, camera position update will seize for the duration of pinching.
      if (!_pinchingScreen)
      {
          _worldNode.position = [self pointToCenterViewOn:_player.position];
      }
  }
  
  //Method that is called by my UIPinchGestureRecognizer. Answer from: https://stackoverflow.com/questions/21900614/sknode-scale-from-the-touched-point?lq=1
  -(void)handleZoomFrom:(UIPinchGestureRecognizer*)recognizer
  {
      CGPoint anchorPoint = [recognizer locationInView:recognizer.view];
      anchorPoint         = [self convertPointFromView:anchorPoint];
  
      if (recognizer.state == UIGestureRecognizerStateBegan)
      {
          // No code needed for zooming...
  
          _player.movementMode    = 2; //Stop character from moving from touches.
          _pinchingScreen         = YES; //Notifies 'didFinishUpdate' method that pinching began &amp; camera position update should stop for now.
      }
      else if (recognizer.state == UIGestureRecognizerStateChanged)
      {
          //Technique from the above Stack Overflow link - Commented out.
  //        CGPoint anchorPointInMySkNode = [_worldNode convertPoint:anchorPoint fromNode:self];
  //        
  //        [_worldNode setScale:(_worldNode.xScale * recognizer.scale)];
  //        
  //        CGPoint mySkNodeAnchorPointInScene = [self convertPoint:anchorPointInMySkNode fromNode:_worldNode];
  //        CGPoint translationOfAnchorInScene = CGPointSubtract(anchorPoint, mySkNodeAnchorPointInScene);
  //
  //        _worldNode.position = CGPointAdd(_worldNode.position, translationOfAnchorInScene);
  //        
  //        recognizer.scale = 1.0;
  
  
          //Modified scale: 2.0
          if(recognizer.scale &gt; _previousWorldScale)
          {
              _previousWorldScale = recognizer.scale;
  
              CGPoint anchorPointInMySkNode = [_worldNode convertPoint:anchorPoint fromNode:self];
              [_worldNode setScale:2.0];
              CGPoint worldNodeAnchorPointInScene = [self convertPoint:anchorPointInMySkNode fromNode:_worldNode];
              CGPoint translationOfAnchorInScene  = CGPointSubtract(anchorPoint, worldNodeAnchorPointInScene);
              _worldNode.position = CGPointAdd(_worldNode.position, translationOfAnchorInScene);
  
  
              //[_worldNode runAction:[SKAction scaleTo:2.0 duration:0]]; //This works too.
          }
          //Original scale: 1.0
          if(recognizer.scale &lt; _previousWorldScale)
          {
              _previousWorldScale = recognizer.scale;
  
              CGPoint anchorPointInMySkNode = [_worldNode convertPoint:anchorPoint fromNode:self];
              [_worldNode setScale:1.0];
              CGPoint worldNodeAnchorPointInScene = [self convertPoint:anchorPointInMySkNode fromNode:_worldNode];
              CGPoint translationOfAnchorInScene  = CGPointSubtract(anchorPoint, worldNodeAnchorPointInScene);
              _worldNode.position = CGPointAdd(_worldNode.position, translationOfAnchorInScene);
  
  
              //[_worldNode runAction:[SKAction scaleTo:1.0 duration:0]]; //This works too.
          }
      }
      else if (recognizer.state == UIGestureRecognizerStateEnded)
      {
          // No code needed here for zooming...
  
          _pinchingScreen         = NO; //Notifies 'didFinishUpdate' method that pinching has stopped &amp; camera position update should resume.
          _player.movementMode    = 0; //Resume character movement.
      }
  }
  </code></pre>
  
  <p>So could anyone please tell me, by looking at the above code, why the camera/view shifts to the bottom left upon zooming in? I've sat several days on this problem &amp; I still can't figure it out.</p>