2012-11-20 8 views
10

this question के संबंध में मैं सोच रहा था कि क्या एनएसएनोटिफिकेशन का उपयोग करने के बारे में कोई आम तौर पर स्वीकार किया गया तर्क है, आपके मुख्य धागे में एक पर्यवेक्षक के साथ, जीसीडी का उपयोग करके पृष्ठभूमि थ्रेड से मुख्य धागे तक काम भेजने के लिए?एनएसएनोटिफिकेशन बनाम dispatch_get_main_queue

ऐसा लगता है कि एक अधिसूचना-पर्यवेक्षक सेटअप के साथ आपको पर्यवेक्षक को फाड़ना याद रखना होगा जब आपका दृश्य अनलोड हो जाता है लेकिन फिर आप अधिसूचना को अनदेखा करते हैं, जहां मुख्य धागे को नौकरी भेजने के परिणामस्वरूप ब्लॉक को निष्पादित किया जा सकता है जब दृश्य उतार दिया गया है।

इस तरह, ऐसा लगता है कि अधिसूचनाओं में बेहतर ऐप स्थिरता प्रदान की जानी चाहिए। मुझे लगता है कि प्रेषण विकल्प जीसीडी के बारे में मैंने जो पढ़ा है उससे बेहतर प्रदर्शन प्रदान करता है?

अद्यतन:

मुझे पता है कि सूचनाएं और प्रेषण खुशी से एक साथ काम कर सकते हैं और कुछ मामलों में, एक साथ इस्तेमाल किया जाना चाहिए हूँ। मैं यह पता लगाने की कोशिश कर रहा हूं कि क्या विशिष्ट मामले हैं जहां किसी का उपयोग नहीं किया जाना चाहिए/नहीं।

एक उदाहरण केस: मुख्य कतार पर प्राप्त करने वाले फ़ंक्शन को प्रेषित करने के बजाय प्रेषित ब्लॉक से अधिसूचना को फायर करने के लिए मैं मुख्य थ्रेड का चयन क्यों करूं? (स्पष्ट रूप से दो मामलों में प्राप्त करने वाले समारोह में कुछ बदलाव होंगे, लेकिन अंतिम परिणाम समान प्रतीत होता है)।

+2

वे वास्तव में परस्पर अनन्य विकल्प नहीं हैं। आप बैकग्राउंड थ्रेड पर काम करने के लिए जीसीडी का उपयोग कर सकते हैं, फिर मुख्य थ्रेड पर वापस स्विच करें और एनएसएनोटिफिकेशन भेजें (जिसे उसी धागे पर प्राप्त किया जाता है)। या मैं सवाल समझ नहीं रहा हूँ? – Kitsune

+0

@ किट्स्यून मुझे एहसास है कि दोनों को खुशी से एक साथ इस्तेमाल किया जा सकता है, अगर कोई ज्ञात मामला है जहां एक या दूसरे का हमेशा प्रयोग होता है/बचा जाता है तो मैं उत्सुक हूं। मैं ऐसे उदाहरण देख रहा हूं जहां जीसीडी लगातार पृष्ठभूमि धागे पर काम भेजने के लिए प्रयोग किया जाता है लेकिन कभी-कभी अधिसूचना मुख्य धागे पर लौटने के लिए उपयोग की जाती है और दूसरी बार, जीसीडी मुख्य धागे पर वापस जाने के लिए प्रयोग किया जाता है। – Endophage

+1

आप जानते हैं कि अधिसूचनाएं उसी धागे पर वितरित की जाती हैं जिन्हें वे पोस्ट किए जाते हैं? तो वे "मुख्य धागे पर लौटने" के लिए इस्तेमाल नहीं किया जा सकता है! – Felix

उत्तर

14

NSNotificationCenter और gcd & dispatch_get_main_queue() बहुत अलग उद्देश्यों को पूरा करता है। मैं बात नहीं करता "बनाम" वास्तव में लागू है।

NSNotificationCenter आपके आवेदन के अलग-अलग हिस्सों को डी-युग्मन करने का एक तरीका प्रदान करता है। उदाहरण के लिए ऐप्पल के रीचैबिलिटी नमूना कोड में kReachabilityChangedNotification सिस्टम नेटवर्क स्थिति बदलते समय अधिसूचना केंद्र पर पोस्ट किया गया है। और बदले में आप अपने चयनकर्ता/आमंत्रण को कॉल करने के लिए अधिसूचना केंद्र से पूछ सकते हैं ताकि आप इस तरह की घटना का जवाब दे सकें। (सोचें एयर रेड साइरेन)

gcd दूसरी तरफ काम करने का एक त्वरित तरीका प्रदान करता है आपके द्वारा निर्दिष्ट एक कतार। यह आपको सिस्टम को उन बिंदुओं को बताने देता है जिन पर आपके कोड को विच्छेदित किया जा सकता है और एकाधिक-थ्रेड और बहु-कोर CPUs का लाभ उठाने के लिए अलग से संसाधित किया जा सकता है।

आम तौर पर (लगभग हमेशा) अधिसूचनाओं को उस धागे पर देखा जाता है जिस पर उन्हें पोस्ट किया जाता है। एपीआई के एक टुकड़ा के उल्लेखनीय अपवाद ... के साथ

एपीआई के एक टुकड़ा जहां अवधारणाओं को इन एक दूसरे को काटना NSNotificationCenter की है:

addObserverForName:object:queue:usingBlock: 

यह अनिवार्य रूप से है कि किसी भी अधिसूचना सुनिश्चित करने के लिए एक सुविधाजनक तरीका है दिए गए धागे पर मनाया जाता है। हालांकि "usingBlock" पैरामीटर बताता है कि दृश्यों के पीछे यह gcd का उपयोग कर रहा है।

यहां इसके उपयोग का एक उदाहरण है। मेरी कोड में कहीं मान लीजिए कि एक NSTimer इस विधि हर दूसरे बुला:

-(void)timerTimedOut:(NSTimer *)timer{ 
    dispatch_async(dispatch_get_global_queue(0, 0), ^{ 
     // Ha! Gotcha this is on a background thread. 
     [[NSNotificationCenter defaultCenter] postNotificationName:backgroundColorIsGettingBoringNotification object:nil]; 
    }); 
} 

मैं मेरे लिए एक संकेत के रूप में backgroundColorIsGettingBoringNotification उपयोग करने के लिए मेरे विचार नियंत्रक के दृश्य की पृष्ठभूमि का रंग बदलना चाहते हैं। लेकिन यह एक पृष्ठभूमि धागे पर पोस्ट किया गया है। खैर मैं उपर्युक्त एपीआई का उपयोग केवल यह देखने के लिए कर सकता हूं कि केवल मुख्य धागे पर।निम्नलिखित कोड में viewDidLoad नोट:

@implementation NoWayWillMyBackgroundBeBoringViewController { 
    id _observer; 
} 
-(void)observeHeyNotification:(NSNotification *)note{ 
    static NSArray *rainbow = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     rainbow = @[[UIColor redColor], [UIColor orangeColor], [UIColor yellowColor], [UIColor greenColor], [UIColor blueColor], [UIColor purpleColor]]; 
    }); 
    NSInteger colorIndex = [rainbow indexOfObject:self.view.backgroundColor]; 
    colorIndex++; 
    if (colorIndex == rainbow.count) colorIndex = 0; 
    self.view.backgroundColor = [rainbow objectAtIndex:colorIndex]; 
} 
- (void)viewDidLoad{ 
    [super viewDidLoad]; 
    self.view.backgroundColor = [UIColor redColor]; 
    __weak PNE_ViewController *weakSelf = self; 
    _observer = [[NSNotificationCenter defaultCenter] addObserverForName:backgroundColorIsGettingBoringNotification 
                    object:nil 
                    queue:[NSOperationQueue mainQueue] 
                   usingBlock:^(NSNotification *note){ 
                    [weakSelf observeHeyNotification:note]; 
                   }]; 
} 
-(void)viewDidUnload{ 
    [super viewDidUnload]; 
    [[NSNotificationCenter defaultCenter] removeObserver:_observer]; 
} 
-(void)dealloc{ 
    [[NSNotificationCenter defaultCenter] removeObserver:_observer]; 
} 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{ 
    return (interfaceOrientation == UIInterfaceOrientationPortrait); 
} 
@end 

इस एपीआई के प्राथमिक लाभ होने के लिए है कि अपने को देख ब्लॉक postNotification... कॉल के दौरान कहा जाएगा लगता है। आप मानक एपीआई का इस्तेमाल किया और observeHeyNotification: तरह लागू किया, तो निम्न कोई गारंटी नहीं है कि इसमें कितना समय से पहले अपने प्रेषण ब्लॉक मार डाला गया था होगा वहाँ होगा:

-(void)observeHeyNotification:(NSNotification *)note{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     // Same stuff here... 
    }); 
} 

इस उदाहरण में बेशक आप बस एक पर अधिसूचना पोस्ट नहीं कर सके पृष्ठभूमि धागा, लेकिन यह आसान हो सकता है यदि आप एक ढांचे का उपयोग कर रहे हैं जो इस बात की कोई गारंटी नहीं देता है कि यह किस धागे पर अधिसूचनाएं पोस्ट करेगा।

+0

धन्यवाद, उत्कृष्ट स्पष्टीकरण। बस स्पष्ट करने के लिए, 'addObserverForName' यह सुनिश्चित करता है कि ब्लॉक को उसी थ्रेड में निष्पादित किया गया है जो पर्यवेक्षक बाध्य है (जैसा कि उसी थ्रेड में जिसे आपने' addObserverForName' कहा है)? – Endophage

+0

@ एन्डोफेज नं। 'AddObserverForName के लिए तीसरा पैरामीटर: ऑब्जेक्ट: कतार: उपयोगब्लॉक:' 'NSOperationQueue' है। ब्लॉक को 'NSOperationQueue' द्वारा प्रतिनिधित्व किए गए थ्रेड/कतार पर निष्पादित किया गया है। उत्तर नमूना कोड में मैंने मुख्य कतार/थ्रेड का संदर्भ प्राप्त करने के लिए 'mainQueue 'क्लास विधि का उपयोग किया था। – NJones

+2

आह समझा। तो वास्तव में पर्यवेक्षक की स्थापना करते समय उपयुक्त 'NSNotificationQueue' में गुज़रने के द्वारा उत्पन्न किए गए एक अलग थ्रेड पर एक अधिसूचना प्राप्त की जा सकती है। – Endophage

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