0

私はNSOperationQueueを作成してブロックをキューに追加できますが、各API呼び出しには完了ブロックがあるため、初期呼び出しは次のとおりです。限られていますが、私は完了ブロックの実行に基づいてキューの処理を制限する方法を知らない。iOSがNSBlockOperationを使用して非同期API呼び出しを抑制する

以下のコードでは、誰でもいつでも2つ以上の呼び出し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); 
     }]; 
} 
+0

(willChangeとdidChange呼び出しが本当に重要であることに注意してください、以下を参照)として完成し、独自の操作をマークし、それはありません

  • 2つ以上のAPI呼び出しをいつでも並列に実行できます。 –

  • +0

    NSOperationには既に使用できるcompletionBlockがあります。自分で実装する必要はありません。代わりに、結果を '@ property'に格納してから、あなたの操作を呼び出すときにこれをします:myOperation.completionBlock =^{/ * myOperation.results * /}にアクセスできます。意味がありますか? –

    答えて

    2

    NSOperationをサブクラス化する必要があります。

    ここNSOperationサブクラス化する方法、それをすべて説明して完全なドキュメントです:https://developer.apple.com/reference/foundation/operation

    クイックノート:

    • あなたの「開始」操作はinvokeAPIコールだろうが。次に、あなたのinvokeAPI完了ブロックでは、あなたのコードから

    [self willChangeValueForKey:@"isExecuting"]; 
    [self willChangeValueForKey:@"isFinished"]; 
    self.isExecuting = NO; 
    self.isFinished = YES; 
    [self didChangeValueForKey:@"isExecuting"]; 
    [self didChangeValueForKey:@"isFinished"]; 
    
    +0

    マークさん、ありがとうございます。 NSOperationのサブクラスを含めるように質問を修正した場合、メモリリークや不正アクセスの可能性があるというコメントがあれば感謝します。 –