2017-08-07 7 views
2

UIViewを作成しており、多くの非同期タスクをUIViewControllerで実行しています。ある時点で、UIViewを削除して、実行中のすべてのタスクを停止したいと考えています。ただし、removeFromSuperview()コールはタスクを停止しません。私はそれを行うことができる方法はありますか?すべての非同期タスクをUIViewで中止する

サンプルコード

class ViewController: UIViewController { 

    let v = SomeView() 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     v.frame = CGRect(x: 0, y: 0, width: 10, height: 10) 
     self.view.addSubview(v) 

     let v1 = UIButton() 
     v1.frame = CGRect(x: 0, y: 0, width: 100, height: 100) 
     v1.backgroundColor = UIColor.blue 
     v1.addTarget(self, action: #selector(removeV(_:)), for: .touchUpInside) 
     self.view.addSubview(v1) 
    } 

    func removeV(_ sender: UIButton) { 
     print("V REMOVED") 
     v.removeFromSuperview() 
    } 
} 

class SomeView: UIView { 
    override func draw(_ rect: CGRect) { 
     DispatchQueue.global().async { 
      var c = 0 
      while true { 
       print(String(c) + " DOING SOME TASK") 
       c += 1 
       sleep(1) 
      } 
     } 
    } 
} 

例ログ

0 DOING SOME TASK 
1 DOING SOME TASK 
V REMOVED 
2 DOING SOME TASK 
3 DOING SOME TASK 
4 DOING SOME TASK 
... 
+0

これは、あるタスクが長期間にわたって行われていることを示す例です。ビューを削除すると、そのようなタスクはすべて停止します。 –

答えて

3

:能力を追加するには

あなたはOperationOperationQueue 簡単な例を使用する必要がありますバックグラウンドタスクを管理します。たとえば。

//create the dispatch work item 
var dwi2:DispatchWorkItem? 
dwi2 = DispatchWorkItem { 
    var c = 0 
    while true { 
     print(String(c) + " DOING SOME TASK") 
     c += 1 
     sleep(1) 
     if (dwi2?.isCancelled)!{ 
      break 
     } 
    } 
} 

//submit the work item to the default global queue 
DispatchQueue.global().async(execute: dwi2!) 

//cancelling the task after 3 seconds 
DispatchQueue.global().async{ 
    sleep(3) 
    dwi2?.cancel() 
} 

さらに実行を停止するには、ワークブロック内のisCancelledプロパティをチェックする必要があります。

詳細については、thisよく書かれた記事を参照してください。

0

あなたのSomeViewインスタンス内のタスクをキューに格納することができます。詳細についてはdocumentationを確認してください。

ヒント:あなたが必要として、できるだけ多くの操作を追加しますことはできません停止GCDタスク要するに除去

2

-cancelAllOperationsを呼び出すことができます。 DispatchWorkItemを使用してDispatchQueue内のブロックを解除する方法があり

class YourOperation: Operation { 

    func execute() { 
     // Execute your async task here. 

     // call finish() if success finished tasks 
     // call cancel() if some error 
    } 
} 


let queue = OperationQueue() 
let yourOperation = YourOperation() 
queue.addOperation(yourOperation) 

// to stop single operation 
yourOperation.cancel() 



// to stop all operations 
queue.cancelAllOperations() 
+0

ああ、私は全体のUIViewを 'Operation'にすることはできません。 –

+0

なぜこれが必要なのかわからないので、バックグラウンドスレッドでUIを変更することはできません。 –

+2

@VadimKozak Antersがコメントしていることは考えていません。私は、彼がOperationクラスでUIViewをサブクラス化し、彼のビューのデフォルトのcancelAllOperationsを呼び出すことができれば、その答えは「いいえ」になることを意味していたと思います。 – NSNoob

0

NSOperationsであなたの人生を複雑にする必要はありません。フラグを保持する(while true - >while flag)可能性があり、タスクを終了するときにfalseに設定します。このようにして、いつでも必要なときに終了して、フローと可能性のあるエラーを完全に制御することもできます。

さらに頑強にするために、フラグが読み込まれる前にロックレスメモリバリアを使用することができます(異なるスレッドから読み書きするため)。この方法では、CPUのキャッシュとメモリの最適化問題を回避できます。

+0

入力いただきありがとうございます。私は実際には真のループを実行していない、それは単なる構造のイラストです。私は長い期間にわたって多くのタスクが発生しており、実際には動的に生成されるため、それぞれの条件をすべて追跡しているわけではありません。私は基本的には、ユーザーがView Controllerを終了するときにビュー全体を強制終了する必要があります –

関連する問題