Как использовать потоки в swift?
dispatchOnMainThread:^{
NSLog(@"Block Executed On %s", dispatch_queue_get_label(dispatch_get_current_queue()));
}];
Как использовать потоки в swift?
dispatchOnMainThread:^{
NSLog(@"Block Executed On %s", dispatch_queue_get_label(dispatch_get_current_queue()));
}];
В Swift 3.0 было много модернизировано. Запуск чего-то в фоновом потоке выглядит следующим образом:
DispatchQueue.global(qos: .background).async {
print("This is run on the background queue")
DispatchQueue.main.async {
print("This is run on the main queue, after the previous code in outer block")
}
}
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
print("This is run on the background queue")
dispatch_async(dispatch_get_main_queue(), { () -> Void in
print("This is run on the main queue, after the previous code in outer block")
})
})
По состоянию на Swift 1.1 Apple не поддерживала вышеупомянутый синтаксис без каких-либо изменений. Передача QOS_CLASS_BACKGROUND
фактически не работала, вместо этого используйте Int(QOS_CLASS_BACKGROUND.value)
.
Для получения дополнительной информации см. Документация яблок
Рекомендуется определить функцию многократного использования, к которой можно обращаться несколько раз.
например, где-то вроде AppDelegate.swift в качестве глобальной функции.
func backgroundThread(_ delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.value), 0)) {
background?()
let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
dispatch_after(popTime, dispatch_get_main_queue()) {
completion?()
}
}
}
Примечание: в Swift 2.0 замените QOS_CLASS_USER_INITIATED.value выше на QOS_CLASS_USER_INITIATED.rawValue вместо
A. Чтобы запустить процесс в фоновом режиме с задержкой в 3 секунды:
backgroundThread(3.0, background: {
// Your background function here
})
Б. Чтобы запустить процесс в фоновом режиме, затем выполнить завершение на переднем плане:
backgroundThread(background: {
// Your function here to run in the background
},
completion: {
// A function to run in the foreground when the background thread is complete
})
C. Для задержки на 3 секунды - обратите внимание на использование параметра завершения без параметра фона:
backgroundThread(3.0, completion: {
// Your delayed function here to be run in the foreground
})
Дэн Болье отвечает в swift5 (также работает с swift 3.0.1).
extension DispatchQueue {
static func background(delay: Double = 0.0, background: (()->Void)? = nil, completion: (() -> Void)? = nil) {
DispatchQueue.global(qos: .background).async {
background?()
if let completion = completion {
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: {
completion()
})
}
}
}
}
DispatchQueue.background(delay: 3.0, background: {
// do something in background
}, completion: {
// when background job finishes, wait 3 seconds and do something in main thread
})
DispatchQueue.background(background: {
// do something in background
}, completion:{
// when background job finished, do something in main thread
})
DispatchQueue.background(delay: 3.0, completion:{
// do something in main thread after 3 seconds
})
Swift 3 использует новый класс DispatchQueue
для управления очередями и потоками. Чтобы запустить что-то в фоновом потоке, вы должны использовать:
let backgroundQueue = DispatchQueue(label: "com.app.queue", qos: .background)
backgroundQueue.async {
print("Run on background thread")
}
Или если вы хотите что-то в двух строках кода:
DispatchQueue.global(qos: .background).async {
print("Run on background thread")
DispatchQueue.main.async {
print("We finished that.")
// only back on the main thread, may you access UI:
label.text = "Done."
}
}
Вы также можете получить подробную информацию о GDC в Swift 3 в этом учебнике.
Swift 2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
//All stuff here
})
Вам нужно отделить изменения, которые вы хотите запустить в фоновом режиме, из обновлений, которые вы хотите запустить в пользовательском интерфейсе:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
// do your task
dispatch_async(dispatch_get_main_queue()) {
// update some UI
}
}
Swift 4.x
Поместите это в некоторый файл:
func background(work: @escaping () -> ()) {
DispatchQueue.global(qos: .userInitiated).async {
work()
}
}
func main(work: @escaping () -> ()) {
DispatchQueue.main.async {
work()
}
}
и затем назовите его там, где вам нужно:
background {
//background job
main {
//update UI (or what you need to do in main thread)
}
}
В Swift 4.2 и Xcode 10.1
У нас есть три типа очередей:
1. Основная очередь. Главная очередь - это последовательная очередь, которая создается системой и связана с основным потоком приложения.
2. Глобальная очередь. Глобальная очередь - это параллельная очередь, которую мы можем запросить относительно приоритета задач.
3. Пользовательские очереди: могут быть созданы пользователем. Настраиваемые параллельные очереди всегда отображаются в одну из глобальных очередей путем указания свойства Quality of Service (QoS).
DispatchQueue.main//Main thread
DispatchQueue.global(qos: .userInitiated)// High Priority
DispatchQueue.global(qos: .userInteractive)//High Priority (Little Higher than userInitiated)
DispatchQueue.global(qos: .background)//Lowest Priority
DispatchQueue.global(qos: .default)//Normal Priority (after High but before Low)
DispatchQueue.global(qos: .utility)//Low Priority
DispatchQueue.global(qos: .unspecified)//Absence of Quality
Все эти очереди могут быть выполнены двумя способами
1. Синхронное исполнение
2. Асинхронное выполнение
DispatchQueue.global(qos: .background).async {
// do your job here
DispatchQueue.main.async {
// update ui here
}
}
//Perform some task and update UI immediately.
DispatchQueue.global(qos: .userInitiated).async {
// Perform task
DispatchQueue.main.async {
// Update UI
self.tableView.reloadData()
}
}
//To call or execute function after some time
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
//Here call your function
}
//If you want to do changes in UI use this
DispatchQueue.main.async(execute: {
//Update UI
self.tableView.reloadData()
})
Из AppCoda: https://www.appcoda.com/grand-central-dispatch/
//This will print synchronously means, it will print 1-9 & 100-109
func simpleQueues() {
let queue = DispatchQueue(label: "com.appcoda.myqueue")
queue.sync {
for i in 0..<10 {
print("🔴", i)
}
}
for i in 100..<110 {
print("Ⓜ️", i)
}
}
//This will print asynchronously
func simpleQueues() {
let queue = DispatchQueue(label: "com.appcoda.myqueue")
queue.async {
for i in 0..<10 {
print("🔴", i)
}
}
for i in 100..<110 {
print("Ⓜ️", i)
}
}
Хорошие ответы, хотя, в любом случае я хочу поделиться своим объектно - ориентированным решением до даты быстрых 5.
пожалуйста, проверьте это: AsyncTask
Концептуально вдохновленный Android AsyncTask, я написал свой собственный класс в Swift
AsyncTask позволяет правильно и легко использовать поток пользовательского интерфейса. Этот класс позволяет выполнять фоновые операции и публиковать результаты в потоке пользовательского интерфейса.
Вот несколько примеров использования
Пример 1 -
AsyncTask(backgroundTask: {(p:String)->Void in//set BGParam to String and BGResult to Void
print(p);//print the value in background thread
}).execute("Hello async");//execute with value 'Hello async'
Пример 2 -
let task2=AsyncTask(beforeTask: {
print("pre execution");//print 'pre execution' before backgroundTask
},backgroundTask:{(p:Int)->String in//set BGParam to Int & BGResult to String
if p>0{//check if execution value is bigger than zero
return "positive"//pass String "poitive" to afterTask
}
return "negative";//otherwise pass String "negative"
}, afterTask: {(p:String) in
print(p);//print background task result
});
task2.execute(1);//execute with value 1
Имеет 2 общих типа:
BGParam
- тип параметра, отправляемого заданию при выполнении. BGResult
- тип результата фонового вычисления.
Когда вы создаете AsyncTask, вы можете добавить эти типы к тому, что вам нужно передать в фоновую задачу и из нее, но если вам не нужны эти типы, вы можете пометить его как неиспользуемый, просто установив его: Void
или с более коротким синтаксисом.: ()
Когда асинхронная задача выполняется, она проходит 3 этапа:
beforeTask:()->Void
вызывается в потоке пользовательского интерфейса непосредственно перед выполнением задачи.backgroundTask: (param:BGParam)->BGResult
вызывается в фоновом потоке сразу послеafterTask:(param:BGResult)->Void
вызывается в потоке пользовательского интерфейса с результатом фоновой задачиПоскольку вопрос OP уже был выше, я просто хочу добавить некоторые соображения скорости:
Я не рекомендую запускать задачи с приоритетом.background thread, особенно на iPhone X, где задача, по-видимому, выделяется на ядрах с малой мощностью.
Вот некоторые реальные данные из вычислительно интенсивной функции, которая читает из файла XML (с буферизацией) и выполняет интерполяцию данных:
Имя устройства /.background/.utility/.default/.userInitiated/.userInteractive
Обратите внимание, что набор данных не одинаковый для всех устройств. Это самый большой на iPhone X и самый маленький на iPhone 5s.
Мне очень нравится ответ Дэн Боулье, но он не работает с Swift 2.2, и я думаю, что мы можем избежать этих неприятных принудительных разворот!
func backgroundThread(delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) {
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) {
background?()
if let completion = completion{
let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
dispatch_after(popTime, dispatch_get_main_queue()) {
completion()
}
}
}
}
Grand Central Dispatch используется для обработки многозадачности в наших приложениях iOS.
Вы можете использовать этот код
// Using time interval
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+1) {
print("Hello World")
}
// Background thread
queue.sync {
for i in 0..<10 {
print("Hello", i)
}
}
// Main thread
for i in 20..<30 {
print("Hello", i)
}
Больше информации используйте эту ссылку: https://www.programminghub.us/2018/07/integrate-dispatcher-in-swift.html
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), {
// Conversion into base64 string
self.uploadImageString = uploadPhotoDataJPEG.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.EncodingEndLineWithCarriageReturn)
})
Многоцелевая функция для потока
public enum QueueType {
case Main
case Background
case LowPriority
case HighPriority
var queue: DispatchQueue {
switch self {
case .Main:
return DispatchQueue.main
case .Background:
return DispatchQueue(label: "com.app.queue",
qos: .background,
target: nil)
case .LowPriority:
return DispatchQueue.global(qos: .userInitiated)
case .HighPriority:
return DispatchQueue.global(qos: .userInitiated)
}
}
}
func performOn(_ queueType: QueueType, closure: @escaping () -> Void) {
queueType.queue.async(execute: closure)
}
Используйте это как:
performOn(.Background) {
//Code
}
в Swift 4.2 это работает.
import Foundation
class myThread: Thread
{
override func main() {
while(true) {
print("Running in the Thread");
Thread.sleep(forTimeInterval: 4);
}
}
}
let t = myThread();
t.start();
while(true) {
print("Main Loop");
sleep(5);
}