4

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).

samvermette
  • 40,269
  • 27
  • 112
  • 144

3 Answers3

1

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.

Bastian
  • 10,403
  • 1
  • 31
  • 40
  • I can't use the viewDidAppear method because I'm not presenting the VC using standard mechanisms (I'm adding the VC's view directly to the view hierarchy). Also, it's not about the view getting loaded but also the setObject: method to do its work. Setting a 0.01 delay did fix it... I'd like to know why... and a better fix (this is more like a hack). – samvermette Jul 27 '11 at 18:43
  • When you call the addSubview the action is not really done.. it will be done with the next update of the view.. which will happen in the runloop after the current function call is done. So I guess you have to start the animation after that.. – Bastian Jul 27 '11 at 19:31
  • Is that what performSelector:afterDelay: does? Is there another way? – samvermette Jul 27 '11 at 21:37
1

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.

Andy
  • 26
  • 1
0

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];
}
Sisu
  • 716
  • 3
  • 6