3

注:
これは単なる概念実証です。
実際のバックグラウンド タスクは、生データの「HTTP Get」を継続的に要求し、メイン スレッドを介して表示することです。オンデマンド。

シナリオ:
1) オンデマンドでバックグラウンド タスク (ループ) を切り替えます。
2) バックグラウンド タスクは、反復ごとにメイン スレッド UI に通知します。
3) キューで実行されるブロック操作は 1 つだけです。

操作方法 1) NSBlockOperation
を使用して、バックグラウンド コードを含めます。
2) 地域の BOOL を使用してループを切り替えます。IBAction経由。

問題
1) コンパイラは BOOL 'isRunning' に強力なリンクとしてフラグを立てています。

このブロックで「自己」を強くキャプチャすると、保持サイクルが発生する可能性があります。


2) ブロック操作を追加する前に、キューに操作があるかどうかを確認しました。
しかし、私は常に次のエラーが発生します。

-[NSOperationQueue addOperation:]: 操作が終了し、キューに入れることができません

この概念実証は、記載されている問題に加えて、機能しているようです。

質問:
1) BOOL が単なるスケーラーであるのに、なぜコンパイルは BOOL 'running' を強い行としてフラグを立てているのですか?
2) キューに何も見つからない場合、別の NSBlockOperation を追加して NSOperationQueue を再利用できないのはなぜですか?

以下はコード全体です。

#define START 0
#define STOP 1

@interface ricViewController ()
@property (assign) BOOL running;
@end

@implementation ricViewController {
    NSOperationQueue *operationQueue;
    NSBlockOperation *blockOperation;
    void (^backgroundBlock)(void);
}

@synthesize running = isRunning;

#pragma mark - ViewController methods

- (void)viewDidLoad {
    operationQueue = [NSOperationQueue new];
    [operationQueue setMaxConcurrentOperationCount:1];
    [operationQueue setName:@"RicQueue"];
    [self buildBackgroundBlock];
    blockOperation = [NSBlockOperation blockOperationWithBlock:backgroundBlock];
    [super viewDidLoad];
}

// -------------------------------------------------------------------------------------------------------------------

- (void)didReceiveMemoryWarning {
    operationQueue = nil;
}

// -------------------------------------------------------------------------------------------------------------------
#pragma mark - Local methods

- (void)buildBackgroundBlock {
    static int k = 0;
    backgroundBlock = ^{
        while (isRunning) {   // 1) *** compiler warning flag: strong link warning ***
            sleep(1);
            if ([NSThread isMainThread]) {
                NSLog(@"{backgroundBlock} *** Main Thread *** ***");
            } else {
                 NSString *myString = [NSString stringWithFormat:@"{backgroundBlock} count = %i", k++];
                 NSLog(myString);
                dispatch_async(dispatch_get_main_queue(), ^{
                    self.dataLabel.text = myString;
                });

            }
        }
    };
}

// -------------------------------------------------------------------------------------------------------------------
#pragma - Action methods

- (IBAction)exitAction:(UIButton *)sender {
    exit(0);
}

// -------------------------------------------------------------------------------------------------------------------

- (IBAction)segmentedAction:(UISegmentedControl *)sender {

    switch (sender.selectedSegmentIndex) {
        case START:
            NSLog(@"START");
            self.running = YES;
            if (operationQueue.operationCount < 1) {
                [operationQueue addOperation:blockOperation]; // 2) *** fatal error on 2nd pass.
            }
            break;
        case STOP:
            NSLog(@"STOP");
            self.running = NO;
            break;
    }
    return;
}

@end

コンソール出力:

BackgroundTask[3759:c07] STOP
BackgroundTask[3759:c07] START
BackgroundTask[3759:1303] {backgroundBlock} count = 0
BackgroundTask[3759:1303] {backgroundBlock} count = 1
BackgroundTask[3759:1303] {backgroundBlock} count = 2
BackgroundTask[3759:1303] {backgroundBlock} count = 3
BackgroundTask[3759:1303] {backgroundBlock} count = 4
BackgroundTask[3759:1303] {backgroundBlock} count = 5
BackgroundTask[3759:1303] {backgroundBlock} count = 6
BackgroundTask[3759:1303] {backgroundBlock} count = 7
BackgroundTask[3759:c07] STOP
BackgroundTask[3759:1303] {backgroundBlock} count = 8
4

1 に答える 1