Ios NSOperationQueue';s addOperation:操作已完成,无法排队?
注意:Ios NSOperationQueue';s addOperation:操作已完成,无法排队?,ios,objective-c,nsoperationqueue,cloudkit,nsblockoperation,Ios,Objective C,Nsoperationqueue,Cloudkit,Nsblockoperation,注意: 这只是概念的证明。 真正的后台任务是不断请求原始数据的“HTTP Get”,并通过主线程显示它;随需应变。 场景: 1) 根据需要切换后台任务(循环) 2) 后台任务在每次迭代时通知主线程UI。 3) 队列中仅运行一(1)个块操作。 操作方法 1) 使用NSBlockOperation包含背景代码。 2) 使用区域BOOL切换循环;通过IBAction。 问题 1) 编译器将布尔值“正在运行”标记为强链接: 在这一块中强烈地捕捉“自我”很可能会导致保留 循环 2) 在尝试添加块操
这只是概念的证明。
真正的后台任务是不断请求原始数据的“HTTP Get”,并通过主线程显示它;随需应变。
场景:
1) 根据需要切换后台任务(循环)
2) 后台任务在每次迭代时通知主线程UI。
3) 队列中仅运行一(1)个块操作。 操作方法
1) 使用NSBlockOperation包含背景代码。
2) 使用区域BOOL切换循环;通过IBAction。 问题
1) 编译器将布尔值“正在运行”标记为强链接:
在这一块中强烈地捕捉“自我”很可能会导致保留 循环
2) 在尝试添加块操作之前,我检查了队列上是否有任何操作
但我总是遇到以下错误:
-[NSOperationQueue addOperation:]:操作已完成,无法排队 除了上述问题外,这一概念证明似乎也在发挥作用 问题:
1) 当BOOL仅仅是一个scaler时,为什么编译器会将它标记为一个强行
2) 如果在队列中找不到NSBlockOperation,为什么我不能通过添加另一个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
我做了进一步的研究,发现,
*我必须根据每个“addOperation”*重新创建NSBlockOperation对象,因为NSOperationQueue拒绝对相同的NSOperation对象重新排队。
因此,以下解决方案:
- (IBAction)segmentedAction:(UISegmentedControl *)sender {
switch (sender.selectedSegmentIndex) {
case START:
NSLog(@"START");
self.running = YES;
blockOperation = nil;
[self buildBackgroundBlock];
blockOperation = [NSBlockOperation blockOperationWithBlock:backgroundBlock];
[operationQueue addOperation:blockOperation];
break;
case STOP:
NSLog(@"STOP");
self.running = NO;
break;
}
}
…至于编译器,将BOOL“isRunning”与静态“self”关联起来:在这一块中强烈地捕捉“自我”很可能导致再培训 循环 所有对“自我”的引用都应通过薄弱环节。
- (IBAction)segmentedAction:(UISegmentedControl *)sender {
switch (sender.selectedSegmentIndex) {
case START:
NSLog(@"START");
self.running = YES;
blockOperation = nil;
[self buildBackgroundBlock];
blockOperation = [NSBlockOperation blockOperationWithBlock:backgroundBlock];
[operationQueue addOperation:blockOperation];
break;
case STOP:
NSLog(@"STOP");
self.running = NO;
break;
}
}
- (void)buildBackgroundBlock {
static int k = 0;
BOOL myRunning = isRunning;
__weak ricViewController *weakObject = self;
backgroundBlock = ^{
while (myRunning) {
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(), ^{
weakObject.dataLabel.text = [myString copy];
});
}
}
};
}