迅速にスレッドを使用する方法?
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
})
B.バックグラウンドでプロセスを実行するには、フォアグラウンドで完了を実行します。
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でのDan Beaulieuの答え(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")
}
あるいは、2行のコードで何かしたい場合は、
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."
}
}
Swift 3のGDCに関する詳細な情報は このチュートリアル にもあります。
スイフト2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
//All stuff here
})
バックグラウンドで実行したい変更と、UIで実行したい更新とを区別する必要があります。
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では
3種類のキューがあります。
1. Main Queue:メインキューは、システムによって作成され、アプリケーションのメインスレッドに関連付けられたシリアルキューです。
2. Global Queue:グローバルキューはタスクの優先順位に関して要求できる並行キューです。
3.カスタムキュー:はユーザーが作成できます。カスタムコンカレントキューは、Quality of Serviceプロパティ(QoS)を指定することによって、常にグローバルキューの1つにマッピングされます。
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
これらすべてのキューは2つの方法で実行できます。
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)
}
}
それでも、良い答えは、とにかく私のオブジェクト指向ソリューションSwift 5では最新を共有したいことです。
チェックしてください: AsyncTask
概念的にはAndroidのAsyncTaskに触発されて、私はSwiftで私自身のクラスを書いた
AsyncTaskを使用すると、UIスレッドを正しく簡単に使用できます。このクラスを使用すると、バックグラウンド操作を実行して結果をUIスレッドに公開できます。
ここにいくつかの使用例があります
例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
name__に設定するか、短い構文を使用して未使用としてマークできます。 :()
非同期タスクが実行されると、3つのステップを経ます。
beforeTask:()->Void
はタスクが実行される直前にUIスレッドで呼び出されます。backgroundTask: (param:BGParam)->BGResult
afterTask:(param:BGResult)->Void
OPの質問はすでに上記のように回答されているので、速度に関する考慮事項をいくつか追加します。
特にタスクが低電力コアに割り当てられていると思われるiPhone Xで、 .background スレッド優先順位でタスクを実行することはお勧めしません。
これは、XMLファイルから(バッファリングを使用して)読み取り、データ補間を実行する、計算量の多い関数からの実際のデータです。
デバイス名/ .background / .utility / .default / .userInitiated / .userInteractive
データセットはすべてのデバイスで同じというわけではありません。これはiPhone Xで最大、iPhone 5では最小です。
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
私は本当にDan Beaulieuの答えが好きですが、それは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()
}
}
}
}
スレッドの多目的機能
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
}
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), {
// Conversion into base64 string
self.uploadImageString = uploadPhotoDataJPEG.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.EncodingEndLineWithCarriageReturn)
})