注:
これは単なる概念実証です。
実際のバックグラウンド タスクは、生データの「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