3

I want to load some views in thread to avoid UI freeze waiting loading end.

I'm not used to thread so I make a quick test. My code just try to create views in a thread and add this views in the current viewcontroller view in the main thread.

My UIView is working, but for my UILabel I have to wait between 20-60s to have it on the screen.

I make a test with a UIButton and in this case the button display instantly but the label inside the button display with the same delay than my UILabel.

The only way to have it working as I want is to add a [lbl setNeedsDisplay]; in the main thread to force the UILabel to be displayed instantly. Why? Is it possible to do the job without this line?

    dispatch_queue_t queue = dispatch_queue_create("myqueue", NULL);
dispatch_async(queue, ^{

    // NEW THREAD
    UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 48)];
    lbl.text = @"FOO";

    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
    view.backgroundColor = [UIColor redColor];

    // MAIN THREAD
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.view addSubview:lbl];
        [lbl setNeedsDisplay]; // Needeed to see the UILabel. WHY???

        [self.view addSubview:view];
    });
});
dispatch_release(queue);
Alex
  • 653
  • 9
  • 31
  • Creating UIView's is not critical task, you not need to do it in another thread. – Artem Shmatkov Mar 05 '13 at 16:50
  • I'm trying to make a calendar. In this calendar I have 42 buttons for each days in a 6x7 grid and I have to had a dot under each day if there's an event. I add the dot with CALayer as sublayer of the day button and I have some delay displaying this during transition between month. When I look for the reason of this delay it seems to come from the addSubLayer. So I want to add this sublayer in background at the init and make it hidden or not in the main thread. If you have some ideas on this I'm earing you :-) – Alex Mar 05 '13 at 16:56
  • @zakhej If the plan for some decent to heavy data processing, it is. – Mike D Mar 05 '13 at 16:58
  • I would suggest showing us the code you use to calculate the views. That is where your delay is. Adding subviews would typically not give you that kind of delay. I have done a similar calendar view and did not experience this problem. – sosborn Mar 05 '13 at 17:00
  • @sosborn When I comment only this line [self.layer addSublayer:layer]; the delay disappear. I keep the code to create the sublayer. So I think it come from here. How do you make your dot? CALayer, UIImageView... ? – Alex Mar 05 '13 at 17:03
  • @sosborn I look again for my problem, and finaly it was just a perception problem. I use a pageCurl transition between each month. And when I use the addSublayer line, this transition doesn't animate but I still have the transition delay so it looks like delay but not. Thanks! Now I've to find how keep my animation working with this addSublayer line... – Alex Mar 05 '13 at 17:14
  • I finaly find the way to avoid transition slow-down using 42 CALayer. I set shouldRasterize attribute of my views to YES. It work great :) – Alex Mar 06 '13 at 08:01

1 Answers1

5

You should set the text of the label on the main queue as well:

dispatch_async( dispatch_get_main_queue(), ^{
    UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 48)]
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
    lbl.text = @"FOO";
    [self.view addSubview:lbl];
    [self.view addSubview:view];
});

It best to keep all UI stuff on the main queue.

UPDATE:

It appears initWithFrame: is not thread safe (found on the SO answer, see also Threading Considerations in the UIView docs).

Community
  • 1
  • 1
Mike D
  • 4,938
  • 6
  • 43
  • 99
  • It's not working like this. I still have to use [lbl setNeedsDisplay]; – Alex Mar 05 '13 at 16:48
  • We can't make new lines in comments whith return key? – Alex Mar 05 '13 at 16:49
  • Sorry for my first answer, it seems to work. I had to delete the lbl.text = @"FOO"; in the thread too. I think he detect the assignment of the same text in UILabel and he don't force refresh. But I can't understaind why it's not working with uilable but it work with uiview? – Alex Mar 05 '13 at 16:52
  • Thanks mike, but in your update I dont have code in background anymore. Perhaps I miss something because I'm a thread newbee. – Alex Mar 05 '13 at 16:59
  • @Alex If all you are doing is creating views like this, I don't think you will notice a performance hit by staying on the main thread. The general rule is if its the UI, it is on the main thread. – Mike D Mar 05 '13 at 17:01
  • Yes it's just for test purpose. My real code as some perf issue and I try to solve it. You can see my problem in my comments under my question. – Alex Mar 05 '13 at 17:07