#swift #swiftui #swift5.5 #swift-concurrency
Вопрос:
В этом случае асинхронная функция считывает файл и возвращает проанализированное содержимое.
На мой взгляд, я хочу загрузить содержимое из основного потока, а затем обновить представление после завершения.
Я использовал этот шаблон в разных местах и заметил, что в некоторых случаях асинхронный вызов выполняется в основном потоке (путем отладки), а в других — в Thread 4 Queue : com.apple.root.user-initiated-qos.cooperative (concurrent)
потоке
Например:
struct MyView: View {
@State var data = "some data"
var body: some View {
Button("refresh") {
// when the button is pressed refresh it
Task {
await refresh()
}
}.task {
// when the view appears
await refresh()
}
Text("the data is (data)") // write the data which was refreshed async
}
}
func refresh() async {
do {
let res = try await anotherAyncFunction()
data = res // this is presumably wrong and off the main thread - obviously might not be correct but leave here for debug as well
} catch {
print("got error (error)")
}
}
Я создал несколько разных представлений, используя аналогичный шаблон ( .task
async
функции вызова блоков)
В некоторых случаях функции выполняются долго (чтение с диска), и это происходит в основном потоке
Комментарии:
1. Вам может понравиться видео Swift concurrency: за кулисами , в котором рассказывается о том, как Swift Concurrency планирует задачи.
Ответ №1:
Измените Task {
на Task.detached {
.
Из руководства по языку Swift:
Чтобы создать неструктурированную задачу, которая выполняется на текущем исполнителе, вызовите
Task.init(priority:operation:)
инициализатор. Чтобы создать неструктурированную задачу, которая не является частью текущего участника, более конкретно известную как отдельная задача, вызовите методTask.detached(priority:operation:)
класса.
При вызове Task.init
асинхронный код выполняется для текущего участника, который в данном контексте является основным участником. Это приводит к блокировке основного потока.
Вызывая Task.detached
, вы позволяете асинхронной работе выполняться вне основного потока.
Комментарии:
1. Не работает, мой
Task
отсоединен, но он находится в основном потоке.
Ответ №2:
Используя структурированный параллелизм Swift, для запуска кода в фоновом потоке используйте отдельную задачу или (лучше) субъекта.