samvermette
samvermette

Reputation: 40437

UIScrollView's setContentOffset called before new subview is loaded

I have a UIView that I'm sliding in using a UIScrollView. Code looks like this:

[view setObject:object]; // updates a bunch of labels, images, etc
[scrollView addSubview:view];
[scrollView setContentOffset:CGPointMake(320,0) animated:YES];

Problem is, the scrollView doesn't seem to wait for the view to be completely loaded before animating its contentOffset, and so the animation is kinda jerky (almost non-existent on the first slide-in and on older devices). Oddly enough, switching the 3rd line to this fixes it:

[UIView animateWithDuration:0.3 animations:^{
    [scrollView setContentOffset:CGPointMake(320,0) animated:NO];
}];

No lag whatsoever, perfectly smooth slide-in. However, this doesn't trigger any of the UIScrollViewDelegate calls, on which I also depend (but which aren't responsible for the lag).

Any idea of how I could tell the UIScrollView to wait for the view to be completely loaded before animating its contentOffset? Or maybe there's something else that I'm missing?

EDIT: before anyone else suggests it: yes, I did try:

[self performSelector:@selector(slideIn) withObject:nil afterDelay:1];

just to see if it would fix it. And yes it does fix the lag, but this is not an actual solution. performSelector:afterDelay: is never a solution, it's only a superficial fix. Plus, you're making the user wait extra seconds every time (since the actual delay may be much shorter than 1 second depending on the device model).

Upvotes: 4

Views: 1868

Answers (3)

Andy
Andy

Reputation: 26

Performing selector after delay 0.01 works because the invocation is scheduled on the runloop vs. calling the method immediately. For that matter, afterDelay:0.0 may also work. Did not try in this particular case but works in may similar situations.

Upvotes: 1

Bastian
Bastian

Reputation: 10433

have you tried starting the scrolling in the "viewDidAppear" function of the viewcontroller... maybe this is called when the loading is finished.

otherwise try afterdelay with a very short time like 0.01 .. so that the call is scheduled next after the current work is done.

Upvotes: 1

Sisu
Sisu

Reputation: 716

Try this, set contentSize after some delay (here delay is 2 second).

[view setObject:object];
[scrollView addSubview:view];
[self performSelector:@selector(contentSize) withObject:nil afterDelay:2];
}
-(void) contentSize {
[scrollView setContentOffset:CGPointMake(320,0) animated:YES];
}

Upvotes: 0

Related Questions