2013-03-05 3 views
3

Я хочу загрузить некоторые виды в потоке, чтобы избежать завершения загрузки конечного пользователя.UILabel не отображается мгновенно с помощью потока

Я не привык к потоку, поэтому я делаю быстрый тест. Мой код просто пытается создать представления в потоке и добавить эти представления в текущее представление viewcontroller в основном потоке.

Мой UIView работает, но для моего UILabel мне нужно подождать между 20-60 годами, чтобы он был на экране.

Я делаю тест с помощью UIButton, и в этом случае дисплей кнопки мгновенно, но ярлык внутри дисплея кнопки с той же задержкой, что и мой UILabel.

Единственный способ заставить его работать, как я хочу, это добавить [lbl setNeedsDisplay]; в основном потоке, чтобы заставить UILabel отображаться мгновенно. Почему? Можно ли выполнять работу без этой строки?

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); 
+0

Создание UIView - это не критическая задача, вам не нужно делать это в другом потоке. – zakhej

+0

Я пытаюсь создать календарь. В этом календаре у меня есть 42 кнопки для каждого дня в сетке 6x7, и я должен иметь точку под каждым днем, если есть событие. Я добавляю точку с CALayer в качестве подуровня кнопки дня, и у меня есть некоторая задержка, отображающая это во время перехода между месяцами. Когда я ищу причину этой задержки, похоже, это происходит из addSubLayer. Поэтому я хочу добавить этот подслой в фоновом режиме в init и сделать его скрытым или нет в основном потоке. Если у вас есть какие-то идеи по этому поводу, я ухожу :-) – Alex

+0

@zakhej Если план какой-то приличной обработки данных тяжелый, это так. –

ответ

5

Вы должны установить текст метки на главной очереди, а также:

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]; 
}); 

, что лучше держать все UI материал на главной очереди.

UPDATE:

Оказывается initWithFrame: не поточно (находятся на SO answer, смотрите также Threading Considerations в UIView документах).

+0

Это не работает. Мне все еще нужно использовать [lbl setNeedsDisplay]; – Alex

+0

Мы не можем создавать новые строки в комментариях с помощью клавиши возврата? – Alex

+0

Извините за мой первый ответ, похоже, работает. Мне пришлось удалить lbl.text = @ "FOO"; в потоке тоже. Я думаю, он обнаружил назначение того же текста в UILabel, и он не заставляет обновлять. Но я не могу понять, почему он не работает с uilable, но он работает с uiview? – Alex