18

次のタスクを実行する必要があります。

1) sqlite データベースからいくつかのデータを読み取ります

2) データを処理する

3)処理されたデータを使用して、いくつかのチャートを生成します

アプリケーションに多くのデータを入力するユーザーがいる場合、ある日、この分析が遅くなり、UI がフリーズする可能性があります。

では、操作をキャンセルするか、画面を終了するオプションを使用して、ユーザーが UI とやり取りできるようにする正しい処理方法は何ですか?

すべてのタスクに対して単純なスレッドを作成し、キャンセル イベントまたはフラグを使用して各タスクを停止する必要がありますか? または、別の方法がありますか?

例えば:

タスク 1: 必要に応じてプロセスを停止するフラグを使用して、スレッドで sqlite からデータを読み取ります。

タスク 2: 必要に応じてプロセスを停止するフラグを使用して、スレッド内のデータを処理します。

タスク 3: データをサードパーティ コンポーネントに配信します。この時点で、他のコンポーネントで実行中の操作をキャンセルできますか?

私は正しい方法で考えていますか、それとも何かを改善できますか?

4

2 に答える 2

28

これは、GCD (Grand Central Dispatch) を使用して Apple が推奨する最速の方法です。また、ロジックは直線的ですが、メソッド間で分割されていないため、読みやすく理解しやすいです。

これは、必要なweakSelfの「ダンス」を示していることに注意してください。これは、非同期が呼び出されたコントローラーよりも長生きする可能性があるため、それへの弱い参照を作成し、生きているかどうかを確認し、更新するために保持します。

スイフト 4 & 3

 DispatchQueue.global().async() {
      print("Work Dispatched")
      // Do heavy or time consuming work

      // Then return the work on the main thread and update the UI
      // Create weak reference to self so that the block will not prevent it to be deallocated before the block is called.
      DispatchQueue.main.async() {
           [weak self] in
           // Return data and update on the main thread, all UI calls should be on the main thread 
           // Create strong reference to the weakSelf inside the block so that it´s not released while the block is running
           guard let strongSelf = self else {return}
           strongSelf.method()
      }
 }

Objective-C

// To prevent retain cycles call back by weak reference
   __weak __typeof(self) weakSelf = self;  // New C99 uses __typeof(..)

    // Heavy work dispatched to a separate thread
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"Work Dispatched");
        // Do heavy or time consuming work
        // Task 1: Read the data from sqlite
        // Task 2: Process the data with a flag to stop the process if needed (only if this takes very long and may be cancelled often).

        // Create strong reference to the weakSelf inside the block so that it´s not released while the block is running
        __typeof(weakSelf) strongSelf = weakSelf;
        if (strongSelf) {

            [strongSelf method];

            // When finished call back on the main thread:
            dispatch_async(dispatch_get_main_queue(), ^{
                // Return data and update on the main thread
                // Task 3: Deliver the data to a 3rd party component (always do this on the main thread, especially UI).
            });
        }
    });

プロセスをキャンセルする方法は、BOOL 値を含め、実行中の作業が不要になった場合にメイン スレッドから停止するように設定することです。ただし、重い計算を行わない限り、ユーザーはバックグラウンド作業にあまり気付かないため、価値がないかもしれません。リテイン サイクルを防ぐには、次のような弱い変数を使用します。

__weak __typeof(self) weakSelf = self; // Obj-C
[weak self] in

ブロック内で強参照を使用してweakSelfを呼び出します(呼び出し元のVCが解放された場合のクラッシュを防ぐため)。UIViewController や __typeof() 関数 (C99 では __typeof(..) を使用する必要がありますが、以前は __typeof(..) を直接使用できました) のような正確な型を使用して、実際の型を参照できます。

Objective-C

__typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
   [strongSelf method];
}

スイフト 4 & 3

if let weakSelf = self {
   weakSelf.method()
}

また

// If not referring to self in method calls.
self?.method()

注: GCD または Grand Central Dispatch を使用します。これは最も単純で、Apple が推奨する方法であり、コード フローは論理的な順序になっています。

于 2012-08-10T14:10:17.600 に答える
1

これは、メインスレッドから関数を切り離す方法です

[NSThread detachNewThreadSelector:@selector(yourmethode:) toTarget:self withObject:nil];

于 2012-08-10T14:06:02.457 に答える