这是代码
@interface ViewController ()
@property (nonatomic, strong) NSOperationQueue *queue;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_queue = [[NSOperationQueue alloc] init];
NSBlockOperation *aBlockOperation = [[NSBlockOperation alloc] init];
__weak NSBlockOperation* aWeakBlockOperation = aBlockOperation;
[aBlockOperation addExecutionBlock:^{
NSLog(@"queue should still have the operation. And it does. yay!: %@", [_queue operations]); // This should print correctly. It will show the NSBlock operation correctly residing inside the NSOperationQueue
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"Now queue is empty??: %@", [_queue operations]); // This should print as being empty
NSLog(@"And a weak block is nil???: %@", aWeakBlockOperation); // This should print out **nil**
if (![aWeakBlockOperation isCancelled]) {
// Now i have no way to check the operation
}
});
}];
[_queue addOperation:aBlockOperation];
@end
[修改] 目标是进行如下用户交互: 屏幕上有一个包含5个或更多单元格的tableView。当用户单击某个单元格时,后台进程将执行需要一段时间的后台进程。应用程序将以3秒的间隔检查用户是否单击了另一个单元格。如果用户点击了另一个单元格,我应该从队列中取消当前操作,并开始处理用户点击的新操作。
从上面的代码我有两个问题我无法解决。
我如何制作它以便我的弱引用不会在dispatch_after块中释放?把它放在那里的目的是暂停应用程序3秒钟。如果dispatch_after不正确,那么我在那里用什么代码来防止它变成零?
为什么调用dispatch_after后我的NSOperationQueue变空了?有没有办法让它不变空?
答案 0 :(得分:1)
dispatch_after
安排阻止并立即返回。因此,您的NSBlockOperation
的executionBlock几乎没有工作要做 - 它会立即完成并从队列中删除。那时,操作被释放,因此弱引用在稍后调用dispatch_after
块之前变为零。
如果先执行dispatch_after
并从该块内部安排操作,则可能符合您的需要。您可以使用sleep
,但我不建议这样做,因为您将不必要地阻止线程。有关NSOperation和延迟的更多讨论,请参阅this question。
答案 1 :(得分:0)
您可以在dispatch_after块中调度操作,并将aBlockOperation声明为实例变量/属性,因此aWeakBlockOperation不会变为nil。
但是你不需要麻烦NSBlockOperation来实现你的目标。您可以使用dispatch_block_t实例变量,每次单击该列时,您将设置为一个新值(在单击列后需要执行代码的块):
@implementation ViewController
{
dispatch_block_t columnBlock;
}
- (void)columnClicked
{
columnBlock = ^{ ... your code ... };
__weak dispatch_block_t weakColumnBlock = columnBlock;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
dispatch_block_t colBlock = weakColumnBlock;
if (colBlock)
colBlock();
});
}