问题描述
我需要将异步操作放入操作队列,但是,他们需要在另一个
i need to put asynchronous operations into an operation queue, however, they need to execute on after the other
self.operationQueue = [NSOperationQueue new];
self.operationQueue.maxConcurrentOperationCount = 1;
[self.operationQueue addOperationWithBlock:^{
// this is asynchronous
[peripheral1 connectWithCompletion:^(NSError *error) {
}];
}];
[self.operationQueue addOperationWithBlock:^{
// this is asynchronous
[peripheral2 connectWithCompletion:^(NSError *error) {
}];
}];
问题是,由于peripheralN connectWithCompletion是异步的,队列中的操作结束, ,我需要然而模拟,外围N connectWithCompletion是同步的,并等待操作结束,直到异步块执行
the problem is, since peripheralN connectWithCompletion is asynchronous, the operation in queue is ended and the next is executed, i would need however simulate, that peripheralN connectWithCompletion is synchronous and wait with the end of operation, till the asynchronous block executes
所以我需要一个这样的行为,只有使用操作队列
so i would need a behaviour like this, only using the operation queue
[peripheral1 connectWithCompletion:^(NSError *error) {
[peripheral2 connectWithCompletion:^(NSError *error) {
}];
}];
推荐答案
NSBlockOperation
不能处理异步操作,但是不是很难创建 NSOperation
的子类,可以...
NSBlockOperation
can't handle asynchronous operations, but it's not all that hard to create a subclass of NSOperation
that can...
基本上,你需要创建一个 NSOperation
,它接受一个块,将另一个块作为完成处理程序。该块可以这样定义:
Basically, you need to create an NSOperation
that takes a block that takes another block as a completion handler. The block could be defined like this:
typedef void(^AsyncBlock)(dispatch_block_t completionHandler);
然后,在 NSOperation
子类的 start
方法,你需要调用 AsyncBlock
传递 dispatch_block_t
当它完成执行时将被调用。您还需要确保保留 KVO
符合 NSOperation
的 isFinished
和 isExecuting
属性(至少)(请参阅;这是允许 NSOperationQueue
等待,直到你的异步操作完成。
Then, in your NSOperation
subclass's start
method, you need to call your AsyncBlock
passing it a dispatch_block_t
that will be called when it's done executing. You also need to be sure to stay KVO
compliant with NSOperation
's isFinished
and isExecuting
properties (at minimum) (see KVO-Compliant Properties in the NSOperation
docs); this is what allows the NSOperationQueue
to wait until your asynchronous operation is complete.
这样:
- (void)start {
[self willChangeValueForKey:@"isExecuting"];
_executing = YES;
[self didChangeValueForKey:@"isExecuting"];
self.block(^{
[self willChangeValueForKey:@"isExecuting"];
_executing = NO;
[self didChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
_finished = YES;
[self didChangeValueForKey:@"isFinished"];
});
}
请注意 _executing
和 _finished
需要在子类中定义,您需要重载 isExecuting
isFinished
属性返回正确的值。
Note that _executing
and _finished
will need to be defined in your subclass somewhere, and you'll need to override isExecuting
and isFinished
properties to return the correct values.
code> AsyncBlock ,你可以像这样将你的操作添加到队列:
If you put all that together, along with an initializer that takes your AsyncBlock
, then you can add your operations to the queue like this:
[self.operationQueue addOperationWithBlock:^(dispatch_block_t completionHandler) {
[peripheral1 connectWithCompletion:^(NSError *error) {
// call completionHandler when the operation is done
completionHandler();
}];
}];
[self.operationQueue addOperationWithBlock:^(dispatch_block_t completionHandler) {
[peripheral2 connectWithCompletion:^(NSError *error) {
// call completionHandler when the operation is done
completionHandler();
}];
}];
我把一个简单版本这里:。
这只是一个最小的实现,但它应该工作(如果 isCancelled
其中也实现,例如)。
I put together a gist of a simple version of this here: AsyncOperationBlock.It's only a minimum implementation, but it should work (it would be nice if isCancelled
where also implemented, for example).
为完整性而在此复制:
AsyncBlockOperation.h:
#import <Foundation/Foundation.h>
typedef void(^AsyncBlock)(dispatch_block_t completionHandler);
@interface AsyncBlockOperation : NSOperation
@property (nonatomic, readonly, copy) AsyncBlock block;
+ (instancetype)asyncBlockOperationWithBlock:(AsyncBlock)block;
- (instancetype)initWithAsyncBlock:(AsyncBlock)block;
@end
@interface NSOperationQueue (AsyncBlockOperation)
- (void)addAsyncOperationWithBlock:(AsyncBlock)block;
@end
AsyncBlockOperation.m:
#import "AsyncBlockOperation.h"
@interface AsyncBlockOperation () {
BOOL _finished;
BOOL _executing;
}
@property (nonatomic, copy) AsyncBlock block;
@end
@implementation AsyncBlockOperation
+ (instancetype)asyncBlockOperationWithBlock:(AsyncBlock)block {
return [[AsyncBlockOperation alloc] initWithAsyncBlock:block];
}
- (instancetype)initWithAsyncBlock:(AsyncBlock)block {
if (self = [super init]) {
self.block = block;
}
return self;
}
- (void)start {
[self willChangeValueForKey:@"isExecuting"];
_executing = YES;
[self didChangeValueForKey:@"isExecuting"];
self.block(^{
[self willChangeValueForKey:@"isExecuting"];
_executing = NO;
[self didChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
_finished = YES;
[self didChangeValueForKey:@"isFinished"];
});
}
- (BOOL)isFinished {
return _finished;
}
- (BOOL)isExecuting {
return _executing;
}
- (BOOL)isAsynchronous {
return YES;
}
@end
@implementation NSOperationQueue (AsyncBlockOperation)
- (void)addAsyncOperationWithBlock:(AsyncBlock)block {
[self addOperation:[AsyncBlockOperation asyncBlockOperationWithBlock:block]];
}
@end
这篇关于NSOperation等待直到异步块执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!