5

मुझे अपने RestAPI से जानकारी का एक समूह सिंक करना होगा। मुझे काम पूरा करने के लिए 6 RestAPI कॉल करना होगा। मैंने ब्लॉक के साथ एपीआई कॉल डिज़ाइन किए हैं, और यदि कोई है तो एनएसईआरआरआर वापस करें। इन कॉलों में से 3 ने नेस्टेड निष्पादित करना चाहिए क्योंकि पहला कॉल दूसरों को जानकारी देता है और निष्पादन की अनुमति देता है जबकि अन्य 3 कॉल स्वतंत्र रूप से चल सकते हैं। नेटवर्क के प्रदर्शन में सुधार के कारण, मैं निम्नलिखित के रूप में मेरे तुल्यकालन कॉल के लिए बनाया गया:NSBlockOperation, NSOperationQueue और ब्लॉक

  • 1 NSBlockOperation कि पहले नेस्टेड 3 ब्लॉक होता है;
  • 1 एनएसब्लॉकऑपरेशन जिसमें अन्य तीन ब्लॉक शामिल हैं;
  • 1 एनएसब्लॉकऑपरेशन जो मैं "सेफोर" के रूप में उपयोग करता हूं और जब सभी काम करता है तो मुझे बताता है।

अंतिम एनएसब्लॉकऑपरेशन पिछले दो एनएसब्लॉकऑपरेशन पर निर्भरता है।

मेरे पास एक NSOperationQueue भी है जिसमें सभी तीन NSBlockOperation शामिल हैं जहां सेफफोर NSBlockOperation को कतार में अंतिम के रूप में जोड़ा जाता है। परिणाम जो मैं प्राप्त करना चाहता हूं वह है: पहले दो ब्लॉक समवर्ती रूप से बुलाए जाते हैं और जब उनका काम खत्म होता है, तो सैमफोर एनएसब्लॉकऑपरेशन को यूआईएलर्ट मैसेज प्रदान करने वाले उपयोगकर्ता को नियंत्रण और रिटर्न नियंत्रित किया जाता है।

परिणाम यह नहीं बताया गया है कि सिंकअल्बब्लॉक्स जानकारी ब्लॉक के अंत का इंतजार किए बिना नियंत्रण लौटाया जाता है।

कोड कि NSBlockOperation शामिल नीचे:

-(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]; 

} 

और यहाँ, कोड है कि ब्लॉक के ऊपर कॉल:

-(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]; 
    } 

}]; 
} 

क्या गलत है?

+0

क्या आपने एनएसओपरेशन क्यूयूयू को संलग्न कक्षा के एक आवृत्ति चर बनाने की कोशिश की है? –

+0

मैंने किया। मैंने इंस्टेंस वैरिएबल के रूप में घोषित किया और मैंने इसे ViewDidLoad में तुरंत चालू कर दिया। कुछ नहीं बदला। – dpizzuto

उत्तर

3

मुद्दा यह है कि NSBlockOperationसिंक्रोनस ब्लॉक के लिए है। जैसे ही इसके ब्लॉक (ओं) ने निष्पादन समाप्त कर दिया है, यह finished होगा। यदि इसके ब्लॉक एसिंक्रोनस विधियों से आग लगते हैं, तो वे स्वतंत्र रूप से चलेंगे।

उदाहरण के लिए, जब आपका syncUserInfoOperation का ब्लॉक निष्पादित किया जाता है, तो यह [dataSync syncUserInfo:...] को निकाल देता है और फिर स्वयं को मानता है; यह किसी भी पूरा करने वाले हैंडलर को आग लगने की प्रतीक्षा नहीं करता है, या ऐसा कुछ भी नहीं।

इसका एक अच्छा समाधान अपने NSOperation सबक्लास बनाने के लिए है। आप निर्भरता सेट अप आदि को आसान बनाने के लिए शायद अपने प्रत्येक डेटा सिंक प्रकारों के लिए एक बनाना चाहते हैं, लेकिन यह आपके ऊपर है। आप here को कैसे करें ("Configuring Operations for Concurrent Execution" पर अनुभाग को पढ़ना सुनिश्चित करें) के बारे में सब कुछ पढ़ सकते हैं।

आप एक सामान्य NSOperation उप-वर्ग भी बना सकते हैं जो एक ब्लॉक लेता है जिसे असीमित रूप से चलाया जा सकता है। इसके साथ मुख्य मुद्दा यह है कि ऑपरेशन को रद्द करने जैसी चीजों को संभालना मुश्किल हो जाता है, जिसे आप शायद अभी भी चाहते हैं।

+0

मुझे पता चला कि केवल संभावित समाधान NSOperation को उपclass करना है और मैन्युअल रूप से दो प्रकार के एसिंक्रोनस ब्लॉक का प्रबंधन करना है, लेकिन मैंने सोचा कि एक और "प्रकाश" समाधान था। मैं आपके उत्तर के रूप में मान्य हूं और जितनी जल्दी हो सके मैं अपना कार्यान्वयन पोस्ट करूंगा। Thx – dpizzuto

+0

एक "हल्का" समाधान [ग्रांड सेंट्रल डिस्पैच की प्रेषण कतार] का उपयोग करने के लिए हो सकता है (https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/डॉक्टर/यूआईडी/टीपी 400080 9 1-सीएच 102-एसडब्ल्यू 1) ('एनएसओपरेशन 'और परिवार उनके कार्यान्वयन में उन लोगों का उपयोग करते हैं)। कतार बनाने और उन्हें प्रेषित करने के कार्यों के साथ, आप अपने निर्भरता प्रबंधन करने के लिए प्रेषण समूहों को भी देखना चाहते हैं। डिस्पैच कतार बहुत शक्तिशाली और हल्की हैं, लेकिन आप 'NSOperation' में निर्मित कुछ अच्छी कार्यक्षमता खो देंगे। –

संबंधित मुद्दे