2

Мне задали этот вопрос в интервью. Я хочу знать, что будет, если мы дадим UILabel в фоновый поток.Что произойдет, если мы дадим UIlabel фоновому потоку в GCD или NSOperationQueue

+0

Я считаю, что элементы пользовательского интерфейса должны быть изменены только на основной нити. http://stackoverflow.com/a/7905497/4475605 – Adrian

+0

Это зависит от того, что вы пытаетесь сделать с помощью 'UILabel'. – rmaddy

ответ

2

Короткий ответ: «результаты не определены» или «Плохие вещи». UIKit не является потокобезопасным, поэтому вы не знаете, но это не будет хорошо.

Я видел, что изменения в пользовательском интерфейсе требуют времени LOOOOOONNNG, если оно когда-либо, и я видел сбои.

Лучшим ответом является «Не делай этого».

+0

В ios 9 вы получите исключение, если вы измените элементы пользовательского интерфейса в другом потоке – Paulw11

+0

@ Paulw11, действительно? Гарантированное? Какой механизм выдает исключение? –

+0

Вы получаете сообщение об исключении, которое говорит что-то вроде «вы изменяете пользовательский интерфейс в фоновом потоке» – Paulw11

2

Это зависит от того, находится ли метка в иерархии представлений или нет. Общее правило заключается в том, что код, выполняемый фоновым потоком, не должен запускать какие-либо обновления пользовательского интерфейса, такие как view.addSubview или label.setNeedsLayout и т. Д., Тогда можно безопасно поиграть со своей меткой в ​​этом потоке.

Вы должны быть осторожны, хотя после добавления ярлыка в представление даже обновление label.text в фоновом потоке опасно, поскольку оно приведет к недействительности макета его супервизора, чтобы пользовательский интерфейс был обновлен внутри этого потока.

Допустим, что ваш пользовательский класс UILabel делает какое-то время потребляющих операцию в своем конструкторе, который не имеет ничего общего с UI:

class MyFatLabel: UILabel { 
    override init(frame: CGRect) { 
    super.init(frame: frame) 
    self.text = "Lorem ipsum"   
    self.readDataFromDisk() // will block the main thread. 
    } 
} 

Затем, вы можете инициализировать эту метку в отдельном потоке и добавить его в вид в главном (UI) нити таким образом, взаимодействие пользователя с UI не блокируются:

dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) { 
    let label = MyFatLabel(frame: CGRectZero) 

    dispatch_async(dispatch_get_main_queue()) { 
    view.addSubview(label) 
    } 
} 

Короче говоря, вы можете инициализировать новый UILabel (или любой UIResponder) в фоновом потоке, однако, вам должен изменять любые его свойства, запускающие UI upda tes в основной теме.