Ich muss eine Reihe von Informationen von meinem RestAPI synchronisieren. Ich muss 6 RestAPI-Aufrufe ausführen, um die Arbeit abzuschließen. Ich entwarf API-Aufrufe mit Blöcken und gab NSError zurück, wenn es welche gibt. 3 dieser Aufrufe sollten verschachtelt ausgeführt werden, da der erste Aufruf Informationen an andere weitergibt und die Ausführung ermöglicht, während die anderen 3 Aufrufe unabhängig voneinander ausgeführt werden können. Durch die Netzwerk-Performance zu verbessern, entwarf ich meinen Synchronisationsaufruf wie folgt:NSBlockOperation, NSOperationQueue und Blöcke
- 1 NSBlockOperation, die die ersten verschachtelten 3 Blöcke enthalten;
- 1 NSBlockOperation, die andere drei Blöcke enthält;
- 1 NSBlockOperation, die ich als "semphore" benutze und sagt mir, wenn alle Arbeit erledigt ist.
Die letzte NSBlockOperation hat eine Abhängigkeit von den vorherigen zwei NSBlockOperation.
Ich habe auch eine NSOperationQueue, die alle drei NSBlockOperation enthält, wo der Semaphor NSBlockOperation als letzte in der Warteschlange hinzugefügt wird. Das Ergebnis, das ich erreichen würde, ist: erstens zwei Blöcke, die gleichzeitig aufgerufen werden, und wenn ihre Arbeit beendet ist, wird der Semaphor NSBlockOperation aufgerufen und gibt die Steuerelemente an den Benutzer zurück, der UIAlertMessage bereitstellt.
Das Ergebnis ist, daß nicht zuvor erläutert: Kontrollen werden zurückgegeben, ohne das Ende des syncAllBlocksInformation Block wartet.
Unter dem Code, der NSBlockOperation enthält:
-(void)syncAllBlocksInformation:(void(^)(NSError *error))completion{
__block NSError *blockError = nil;
NSOperation *syncUserInfoOperation = [NSBlockOperation blockOperationWithBlock:^{
[dataSync syncUserInfo:tfMail.text password:tfPassword.text completion:^(NSError *error, NSNumber *idUser) {
if(!error){
[dataSync syncUserfilesInfo:idUser completion:^(NSError *error) {
if(!error){
[dataSync syncUserBookings:^(NSError *error) {
if(error){
blockError = error;
}
}];
}
else{
blockError = error;
}
}];
}
else{
blockError = error;
}
}];
}];
NSBlockOperation *otherSyncOperations = [NSBlockOperation blockOperationWithBlock:^{
[dataSync syncNewsInfo:^(NSError *error) {
if(error){
blockError = error;
NSLog(@"error %@",error);
}
}];
}];
[otherSyncOperations addExecutionBlock:^{
[dataSync syncLocationsInfo:^(NSError *error) {
if(error){
blockError = error;
NSLog(@"error %@",error);
}
}];
}];
[otherSyncOperations addExecutionBlock:^{
[dataSync syncExoticAnimalTypesAndAnimals:^(NSError *error) {
if(error){
blockError = error;
NSLog(@"error %@",error);
}
}];
}];
NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"END");
}];
[completionOperation setCompletionBlock:^{
NSLog(@"Syc isEx %i",syncUserInfoOperation.isExecuting);
NSLog(@"other isEx %i",otherSyncOperations.isExecuting);
completion(blockError);
}];
NSOperationQueue *opQueue = [NSOperationQueue new];
[completionOperation addDependency:syncUserInfoOperation];
[completionOperation addDependency:otherSyncOperations];
[opQueue addOperation:syncUserInfoOperation];
[opQueue addOperation:otherSyncOperations];
[opQueue addOperation:completionOperation];
}
Und hier Code, der über Block ruft:
-(IBAction)login:(id)sender{
[self dismissKeyboardOpened:nil];
hud=[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[hud setLabelText:NSLocalizedString(@"login_hud_message", login_hud_message)];
[hud setMode:MBProgressHUDModeIndeterminate];
[self showHudAndNetworkActivity:YES];
[self syncAllBlocksInformation:^(NSError *error) {
[self showHudAndNetworkActivity:NO];
if(!error){
NSLog(@"End LOGIN");
[self showAlert:@"Login" message:@"Login OK" dismiss:YES];
}
else{
[self showAlert:@"Error" message:@"Login NO" dismiss:NO];
}
}];
}
Was ist los?
Haben Sie versucht, 'NSOperationQueue' eine Instanzvariable der einschließenden Klasse zu machen? –
tat ich. Ich habe es als Instanzvariable deklariert und in ViewDidLoad instanziiert. Nichts hat sich geändert. – dpizzuto