Я хочу ограничить количество вызовов API во время полета до 2. Я могу создать NSOperationQueue
и добавить блок в очередь, однако каждый вызов API имеет блок завершения, поэтому первоначальные вызовы ограничены, но я не знаю, как ограничить обработка очереди на основе выполнения блока завершения.
В приведенном ниже коде возможно одновременное выполнение более двух вызовов API.
NSOperationQueue *requestQueue = [[NSOperationQueue alloc] init];
service.requestQueue.maxConcurrentOperationCount = 2;
for (int i = 0; i < 100; i++)
{
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
[self invokeAPI:kAPIName completion:^BOOL(APIResult *result) {
// Do stuff
}
[requestQueue addOperation:operation];
}
}
Буду признателен за любые указатели на правильный шаблон для использования.
EDIT - на основе ответа Марка-Александра
Создали этот класс для инкапсуляции операций, является ли этот подход безопасным с точки зрения памяти, учитывая, что этот класс будет создан из dataAccessService и введен, а также блок завершения, имеющий ссылки на себя, и конец, называемый до выполнения блока завершения?
@interface MAGApiOperation : NSOperation
@property (nonatomic, strong) id<MAGDataAccessServiceProtocol> dataAccessService;
@property (nonatomic, copy) NSString *apiName;
@property (nonatomic, copy) BOOL (^onCompletion)(APIResult *);
+ (instancetype)apiOperationWithName:(NSString *)apiName dataAccessService:(id<MAGDataAccessServiceProtocol>)dataAccessService completion:(BOOL (^)(APIResult *))onCompletion;
@implementation MAGApiOperation
@synthesize executing = _isExecuting;
@synthesize finished = _isFinished;
#pragma mark - Class methods
/// Creates a new instance of MAGApiOperation
+ (instancetype)apiOperationWithName:(NSString *)apiName dataAccessService:(id<MAGDataAccessServiceProtocol>)dataAccessService completion:(BOOL (^)(APIResult *))onCompletion {
MAGApiOperation *operation = [[self alloc] init];
operation.apiName = apiName;
operation.dataAccessService = dataAccessService;
operation.onCompletion = onCompletion;
return operation;
}
#pragma mark - NSOperation method overrides
- (void)start {
[self willChangeValueForKey:@"isExecuting"];
_isExecuting = YES;
[self didChangeValueForKey:@"isExecuting"];
if (!self.isCancelled)
{
[self invokeApiWithName:self.apiName completion:self.onCompletion];
}
}
- (void)finish {
[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
_isExecuting = NO;
_isFinished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
#pragma mark - Private methods
/// Invokes the api with the name then executes the completion block
- (void)invokeApiWithName:(NSString *)apiName completion:(BOOL (^)(VAAInvokeAPIResult *))onCompletion {
[self.dataAccessService invokeAPI:kAPIName completion:^BOOL(APIResult *result) { {
[self finish];
return onCompletion(result);
}];
}
@property
, а затем при вызове операции сделайте следующее: myOperation.completionBlock = ^{ /* Здесь у вас есть доступ к myOperation.results */ }. Имеет смысл? - person Marc-Alexandre Bérubé   schedule 12.10.2016