Search code examples
nsoperationdrawrectnsoperationqueue

NSOperation: addsubview in the main thread and slowness


I have implemented the following NSOperation, to draw N custom views

- (void)main {

    for (int i=0; i<N; i++) {

       << Alloc and configure customView #i >>
       //(customView is a UIView with some drawing code in drawrect)

       [delegate.view addSubview:customView];

    }

    NSLog(@"Operation completed");
}

in the drawRect method of the customView I have

- (void)drawRect {

    <<Drawing code>>

    NSLog(@"Drawed");
    delegate.drawedViews++;

    if (delegate.drawedViews==VIEWS_NUMBER) {
        [delegate allViewsDrawn];
    }
}

So the delegate get the notification when all the views are drawn.

The problem is that after the "Operation completed" log it takes about 5 seconds before I can see the first "Drawed" log.

Why is this happening? And generally speaking, how should I behave in order to find out which line of code is taking so much time being executed?

------ EDIT ------

Sometimes (like 1 out of 10 times) I was getting crashes doing this because I shouldn't call addsubview from the NSOperation since it is not thread-safe. So I changed it to:

[delegate.view  performSelectorOnMainThread:@selector(addSubview:) withObject:customView waitUntilDone:NO];

Now I don't have crashes anymore, but the process takes a very long time to be executed! Like 5 times more than before.

Why is it so slow?


Solution

  • To make things work properly we need to forget about NSOperation and use this "trick"

    dispatch_queue_t main_queue = dispatch_get_main_queue();
    dispatch_async(main_queue, ^{
    
        [self createCustomViews];
    
        dispatch_async(main_queue, ^{
    
            [self addAnotherCustomViewToView];
    
        });
    });