как ios UI update code определен для использования с основной диспетчеризацией - PullRequest
0 голосов
/ 14 ноября 2018

Я читал много примеров кода, я знаю, что обычно вы хотите, чтобы код , который обновляет ваш пользовательский интерфейс , выполнялся в главном потоке.И xcode будет жаловаться во время выполнения, если я что-то упустил.Но только иногда.

Так как же на самом деле определяется код , который обновляет ваш пользовательский интерфейс ?Представляет ли предупреждение обновление пользовательского интерфейса?вызывая reloadData () для UITableView?Как насчет простой установки текста UILabel?Особенно с этими тремя, я видел и использовал это оба пути в моем приложении и не могу действительно понять правило.Тем более, что xcode позволяет мне избежать неприятностей с обоими ... иногда.Я думал, что это было случайно, на какой нити вы были.Но вы на самом деле «всегда» в главном потоке, если только вы не выполняете что-то вроде задачи, которая выполняется в фоновом потоке.

Таким образом, средство проверки основного потока фактически не позволяло мне «уйти» с использованиемreload () и изменение меток в моем viewController ложно.Просто я гарантированно был в главном потоке.

Я думал, что должен был внезапно обернуть каждую смену метки везде в dispatch.async.

Ответы [ 3 ]

0 голосов
/ 14 ноября 2018

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

И вы можете выполнять операции с временем в фоновом потоке, чтобы ваше приложение работало хорошо во время операций. то есть HTTP-запросы, операции с базой данных, длительные циклы, большие вложенные условия и т. д.

Вы можете написать свой код следующим образом ....

// define these methods in your helper class or wherever you want.
public func BACKGROUND_QUEUE(_ codeBlock:@escaping (() -> Void)) -> Void {
    return DispatchQueue.global(qos: DispatchQoS.QoSClass.background).async(execute: codeBlock)
}

public func MAIN_QUEUE(_ codeBlock:@escaping (() -> Void)) -> Void {
    return DispatchQueue.main.async(execute: codeBlock)
}

и используйте вот так.

func fetchData() {

    BACKGROUND_QUEUE {
        //your http request to get some text
        let text = yourResult
        MAIN_QUEUE {
            textLabel.text = text
        }
    }
}
0 голосов
/ 14 ноября 2018

Правило «обновлять пользовательский интерфейс только в главном потоке» охватывает только часть правды, лучше придерживайтесь того, что в документации UIKit указано:

Важно
Используйте классы UIKit только из основного потока вашего приложения или основной очереди отправки, если не указано иное.Это ограничение особенно применимо к классам, производным от UIResponder или связанным с манипулированием пользовательским интерфейсом вашего приложения любым способом.

Это ограничение применяется не только к (видимым) обновлениям того, что представлено пользователю, но и к любые классы UIKit, если не указано иное.

Например, доступ к делегату приложений не влияет на пользовательский интерфейс, но выполнение этого в неосновном потоке вызывает «Нарушение проверки основного потока»”:

DispatchQueue.global().async {
    let shared = UIApplication.shared.delegate
}

// Main Thread Checker: UI API called on a background thread: -[UIApplication delegate]
0 голосов
/ 14 ноября 2018

Xcode разрешение что вы делаете что-то, не означает, что вы должны сделать это.

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

Вещи, которые не являются изменениями пользовательского интерфейса: отправка HTTP-запросов, сокращение чисел, загрузка данных из некоторой базы данных. Они не меняют то, что вы видите на экране.

...