1

내 관심사 : 몇 가지 이유로 3 가지 웹 요청 결과에서 나온 응답을 검색하고 그룹화해야합니다. 그들 중 3 명이 돌아 오면 completeBlock을 호출하여 모든 결과를 전달해야합니다.3 가지 다른 비동기 호출을 처리하는 방법

Session * session = [[ServiceLocator sharedInstance] serviceForName:ServiceLocatorNameUserRepository]; 


NSString * urlMethod = @"POST"; 
NSDictionary * params = @{kParkadomWebServiceUser : session.currentUser.userID}; 

NSMutableDictionary * records = [NSMutableDictionary new]; 

NSOperation * currentBooking = [self performRequestWithPath:API_BOOKING_INPROGRESS 
                 method:urlMethod 
                 parameter:params 
                completion:^(id json, NSError * error) 
                { 
                 records[@"current"] = error ? error : json; 

                }]; 

NSOperation * upcomingBookings = [self performRequestWithPath:API_BOOKING_UPCOMING 
                 method:urlMethod 
                 parameter:params 
                completion:^(id json, NSError * error) 
                { 
                 records[@"upcoming"] = error ? error : json; 

                }]; 

NSOperation * pastBookings = [self performRequestWithPath:API_BOOKING_HISTORY 
                method:urlMethod 
               parameter:params 
               completion:^(id json, NSError * error) 
               { 
                records[@"past"] = error ? error : json; 

               }]; 


NSBlockOperation * completionOperation = [NSBlockOperation blockOperationWithBlock:^{ 
    completion([records copy], nil); 
}]; 
[completionOperation addDependency:currentBooking]; 
[completionOperation addDependency:upcomingBookings]; 
[completionOperation addDependency:pastBookings]; 

[[NSOperationQueue mainQueue] addOperation:completionOperation]; 

완료 분명 항목 매개 변수로 주어진 완료 블록 : NSOperation API를 사용하여, 나는 그런 일을 할 수 있었다. performRequestWithPath : method : 매개 변수 : 완료 : NSOperation을 만들고이를 글로벌 대기열에 추가 한 다음 반환하므로 여기에 3 개의 웹 호출이 있습니다. 그런 다음 블록 작업을 만들고 3 이전 블록에 종속성을 추가하므로 3 블록 완료 전에 시작되지 않습니다.

내 관심사는 NSMutableArray 문제입니다. 이런 일을하는 것은 좋지 않은 디자인 인 것 같아요. 케이스 2의 통화가 정확히 똑같은 시간에 끝나면 정말 버그 증명인지 확실하지 않습니다. (필자는 perform ... : 메소드에서 완료 블록이 메인 큐에서 호출됨을 확인했다).

의견이 있으십니까? 제안, 비판, 이론 ... 나는 모두 열려 있습니다 :)

답변

1

동기화를 추가해야합니다. 코드에서 예를 들어

@synchronized(myArray) { 
    [myArray doSomething]; 
} 

:

@synchronized(records) { 
    records[@"past"] = error ? error : json; 
} 

편집 : gnasher729이 좋은 점을 가져다 @ 그들이 완료 블록 주 스레드에서 실행되는 경우, 다음 동기화를위한 필요가 없다.

2

"레코드"사전이 비동기 호출에서 추가되는 키/값의 단일 목적으로 사용되는 경우 @ 세 개의 값을 추가하는 코드 주위에 {...}을 동기화 (기록)합니다.

완료 블록이 주 큐에서 실행되면 동시에 실행할 수 없습니다. 그러나 코드를주의 깊게 확인해야합니다. 완료 블록이 완료되기 전에 세 가지 작업이 완료 될 수 있습니다!

+0

완료 블록이 주 스레드에서 실행되는지 확인했지만, 어쨌든 @synchronised를 사용하는 것이 더 안전하고 기분이 좋아졌습니다 :) –

+0

addDepency는 completionBlock이 호출되기 전에 막을 것이라고 생각했습니다. 3 블록 완료 했습니까? –

+0

동기화 된 블록으로는 충분하지 않습니다. 또한 NSDictionary 내에서 접촉하는 값이 원자 적으로 액세스되는지 확인해야합니다. –

관련 문제