Question

I'm having problems adding subviews to a scrollview sequentially.

I've got a JSON response coming back from the server which I parse into an array of Business objects, and I send off to the function updateCarousel, which looks like this:

-(void) updateCarousel: (NSArray *)response{
    if(response && response.count>0){
        int i=0;
        self.scrollView.hidden=NO;
        [self.scrollView setNeedsDisplay];
        self.pageControl.hidden=NO;

        [self.scrollView setContentOffset:CGPointMake(0, 0) animated:NO];

        for (Business *business in response){ 
            if (i >= MAX_INITAL_SEARCH_RESULTS)
                 break;

        CGRect frame;
        frame.origin.x = self.scrollView.frame.size.width * i;
        frame.origin.y = 0;

        frame.size = scrollView.frame.size;

        CardView *cardView = [[CardView alloc] initWithBusinessData:business andFrame:frame];


        //I've tried the following code with and without wrapping it in a GCD queue
        dispatch_queue_t addingQueue = dispatch_queue_create("adding subview queue", NULL);
        dispatch_async(addingQueue, ^{
            [self.scrollView addSubview:cardView];
        });
        dispatch_release(addingQueue);

        cardView.backgroundColor = [UIColor colorWithWhite:1 alpha:0];            
        i++;

        self.scrollView.contentSize = CGSizeMake(i*(self.scrollView.frame.size.width), self.scrollView.frame.size.height);
        self.pageControl.numberOfPages=i;

    }
}else{
    self.scrollView.hidden=YES;
    self.pageControl.hidden=YES;
    NSLog(@"call to api returned a result set of size 0");
}

The result - despite the many things I've tried - is always the same: the scrollView adds the subviews all at once, not as they are processed through the loop. I don't understand how this is possible. If I add a sleep() at the end of the loop, it somehow waits for the whole loop to be over before it shows the subviews as added. How does it even know how long the results array is? I'm at my wits' end, please help.

Was it helpful?

Solution

I assume you are not using any extra threads to process the data. What you experience is the application is stuck executing your method. Even though you add your subviews one by one (with a sleep between them), no other piece of code is executed to handle your adding.

1. You can use another thread to load the data and add subviews but this needs to be synchronized to the main thread (more complicated).

2 You can break your method in multiple calls. Between 2 calls of your load method, other pieces of code are allowed to execute and this means the scrollview will be able to process/display your subviews one by one.

You will need to change your loading method to something like this:


- (void)updateCarouselStep:(NSNumber*)loadIndex
{
    if (response && response.count > 0)
    {
        // Here add only a subview corresponding to loadIndex


        // Here we schedule another call of this function if there is anything 
        if (loadIndex < response.count - 1)
        {
            [self performSelector:@selector(updateCarouselStep:) withObject:[NSNumber numberWithInt:(loadIndex+1) afterDelay:0.5f];
        }
    }

}


This is just one basic solution to the problem. For example, you need to take into consideration what happens if you update response data before you finish loading the previous one.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top