Мне задали этот вопрос в интервью. Я хочу знать, что будет, если мы дадим UILabel
в фоновый поток.Что произойдет, если мы дадим UIlabel фоновому потоку в GCD или NSOperationQueue
ответ
Короткий ответ: «результаты не определены» или «Плохие вещи». UIKit не является потокобезопасным, поэтому вы не знаете, но это не будет хорошо.
Я видел, что изменения в пользовательском интерфейсе требуют времени LOOOOOONNNG, если оно когда-либо, и я видел сбои.
Лучшим ответом является «Не делай этого».
В ios 9 вы получите исключение, если вы измените элементы пользовательского интерфейса в другом потоке – Paulw11
@ Paulw11, действительно? Гарантированное? Какой механизм выдает исключение? –
Вы получаете сообщение об исключении, которое говорит что-то вроде «вы изменяете пользовательский интерфейс в фоновом потоке» – Paulw11
Это зависит от того, находится ли метка в иерархии представлений или нет. Общее правило заключается в том, что код, выполняемый фоновым потоком, не должен запускать какие-либо обновления пользовательского интерфейса, такие как 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 в основной теме.
Я считаю, что элементы пользовательского интерфейса должны быть изменены только на основной нити. http://stackoverflow.com/a/7905497/4475605 – Adrian
Это зависит от того, что вы пытаетесь сделать с помощью 'UILabel'. – rmaddy