MScottWaller
MScottWaller

Reputation: 3573

The movement of UIImageView lags

I'm making the trim editor for a waveform, and the movement lags, but only sometimes.

First I'll run the app, and it works perfectly. This is what I want to happen: https://www.youtube.com/watch?v=_JaJBMR07Vw

Then I'll run it again, without changing any code, and the movement lags. Here is the video for that: https://www.youtube.com/watch?v=9fZTV877hSA

Sometimes it works and sometimes it doesn't.

For a brief overview of how it works: I have a waveform that a user can zoom into or pan. The waveform is divided into samples, so first I find the samples underneath the trim editor's x coordinates, and then when the samples change because of a zoom or pan, I work backwards, figuring out which samples the trim editor should be under, and I move the trim editor and its components to the new corresponding samples.

Here is how I initialize

@property (strong, nonatomic) UIView *editor;
@property (nonatomic, strong) UIPanGestureRecognizer *panGesture;
@property (nonatomic, assign) CGFloat leftHandleSamples;
@property (nonatomic, assign) CGFloat rightHandleSamples;
@property CGFloat leftXDimension;
@property CGFloat rightXDimension;

Then I synthesize those.

Then I add this gestureRecognizer in viewDidLoad:

self.waveformPanRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleWaveformPanGesture:)];
    self.waveformPanRecognizer.delegate = self;
    [self.waveform addGestureRecognizer:self.waveformPanRecognizer];

And then this

-(IBAction)edit:(id)sender {

    if (player.duration) {


        editor = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.waveform.frame.size.width/2, 22)];
        [editor setCenter: CGPointMake(self.waveform.center.x, self.waveform.center.y)];


        editor.backgroundColor = [UIColor grayColor];
        editor.alpha = .75;
        [self.view addSubview:editor];

        leftHandleSamples = self.waveform.zoomStartSamples + (self.waveform.zoomEndSamples-self.waveform.zoomStartSamples) * (leftHandle.frame.origin.x) / self.waveform.bounds.size.width;

        rightHandleSamples = self.waveform.zoomStartSamples + (self.waveform.zoomEndSamples-self.waveform.zoomStartSamples) * (rightHandle.frame.origin.x +rightHandle.frame.size.width) / self.waveform.bounds.size.width;

    }
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}


- (IBAction)handleWaveformPanGesture:(UIPanGestureRecognizer *)recognizer {

    leftXDimension = ((leftHandleSamples - self.waveform.zoomStartSamples)/(self.waveform.zoomEndSamples-self.waveform.zoomStartSamples)) *(self.waveform.frame.size.width);

    rightXDimension = ((rightHandleSamples - self.waveform.zoomStartSamples)/(self.waveform.zoomEndSamples-self.waveform.zoomStartSamples)) *(self.waveform.frame.size.width);

    editor.center = CGPointMake((rightXDimension - leftXDimension)/2 + leftXDimension, editor.center.y);

}

So what happens is this:

Let's say that leftHandlesample 325 (which is actually part of the waveform) is at x axis location 20. When the user pans the waveform to the left, let's say leftHandleSample 325 is then at x axis location 10.

The pan gesture above tells the editor to move along with the waveform so that the left handle on the trim editor should also go to x axis location 10.

So the leftHandleSample doesn't update. Only the x value is recalculated depending on where the sample is located after the user moves the waveform.

But there seems to be a lag (only some of the time) and that's what is baffling.

What should I be doing? Thanks.

Upvotes: 0

Views: 236

Answers (1)

Jesse Rusak
Jesse Rusak

Reputation: 57168

So, you've got two gesture recognizers which both trigger when the user pans. One of them updates the waveform's location based on the user's gesture. The other ignores the user's gesture, but uses its action method to update the handle position based on the waveform's current location.

The reason you can get lag here is that you're not controlling the order in which the waveform and the handle are updated. If in each frame, the waveform gesture recognizer triggers first, and then the handle's recognizer runs second, the final positions of both views will be fine (as in your first video). If, however, the order is reversed, the handle will first update based on the previous location of the waveform, and then the waveform will update based on the gesture recognizer. The result is that the handle will be one frame behind, which gives the lag you see.

Since the order those recognizers are triggered in is not specified, sometimes you're lucky and sometimes you're not.

The solution is to not use a gesture recognizer to update your handle. When the waveform updates, it should tell the handle to update by calling some method on it, sending a notification, using a delegate protocol, using KVO, etc.

Upvotes: 1

Related Questions