13

का उपयोग कब करें मैं एक ऑब्जेक्ट (1-से-एन रिलेशनशिप) की कई घटनाओं पर एकाधिक पर्यवेक्षक रखना चाहता हूं।NSNotificationCenter

इस कार्य को प्राप्त करने के लिए एक तंत्र NSNotificationCenter द्वारा प्रदान किया गया है। मेरी समस्या के लिए उपयोग किए जाने पर तंत्र काफी अधिक दिखता है।

कैसे मैं इसे मैन्युअल NSNotificationCenter के उपयोग के बिना करना होगा:

- (void)addDelegate:(id<DelegateProtocol>)delegate; 
- (void)removeDelegate:(id<DelegateProtocol>)delegate; 

मेरी वस्तु से जोड़ सकते हैं और पर्यवेक्षकों हटाने के लिए।

- (void)someEventFired:(NSObject<NSCopying> *)eventData 
{ 
    for (id delegate in delegates) { 
     NSObject *data = [eventData copy]; 
     [delegate someEventFired:data]; 
    } 
} 

इस तंत्र सीधी-सपाट और अतिरिक्त तार को साझा किए वस्तुओं के बिना लागू करने के लिए सरल है।

  • क्या NSNotificationCenter के अलावा आईओएस ढांचे में 1-से-एन प्रतिनिधियों (जैसे सी # घटनाओं) के लिए कोई आधिकारिक पैटर्न है?
  • NSNotificationCenter कब उपयोग किया जाना चाहिए और कब नहीं?
  • जब मैं यहां सुझाव दे रहा हूं कि एक कार्यान्वयन कब किया जाए और कब नहीं किया जाए?
+0

मैं शायद ही कभी, या कभी, NSNotificationCenter का उपयोग करता हूं लेकिन आपके द्वारा वर्णित उसी विधि के साथ चला जाता है। मैंने कई वर्षों तक कई आईओएस ऐप्स (मैं 50 से ऊपर ऐप्स कहूंगा) में इसका इस्तेमाल किया है, मैंने अब तक कोई समस्या नहीं देखी है। एक संभावित गॉचा यह हो सकता है कि आपको कभी-कभी पर्यवेक्षकों को हटाने के लिए निश्चित होना आवश्यक हो, या उम्मीद के बाद उन्हें रिहा नहीं किया जा सकता क्योंकि उन्हें प्रतिनिधियों के रखवाले द्वारा बनाए रखा जाता है। – Jonny

+0

मुझे लगता है कि भले ही NSNotificationCenter दृष्टिकोण नहीं है जिसे हम सी # से जानते हैं, हमें अभी भी उस विशिष्ट प्लेटफ़ॉर्म के लिए डिज़ाइन पैटर्न का उपयोग करने पर ध्यान देना चाहिए, जिसके लिए हम काम कर रहे हैं। उस ने कहा, मैं अब कई ऐप्स में NSNotificationCenter के साथ गया था (हालांकि आप जितने भी नहीं), और मुझे नहीं लगता कि कोड इसके माध्यम से और भी खराब हो गया है। – Etan

उत्तर

14

सम्मेलन के अनुसार, प्रतिनिधियों को शायद केवल 1: 1 संबंधों के लिए उपयोग किया जाना चाहिए। क्या तुम सच में 1 की जरूरत है:

  1. आप उल्लेख किया है, NSNotificationCenter: कार्यक्षमता के इस प्रकार के लिए एन रिश्ते, आप दो विकल्प हैं।
  2. Key-Value Observing (जिसे केवीओ भी कहा जाता है)।

केवीओ उपयुक्त है यदि आप केवल इस बात की परवाह करते हैं कि किसी ऑब्जेक्ट की किसी विशेष संपत्ति में परिवर्तन कब होता है। अन्यथा, आपको वास्तव में NSNotificationCenter का उपयोग करने पर विचार करना चाहिए। आपको तब भी अधिसूचित किया जा सकता है जब कोई विशिष्ट ऑब्जेक्ट उस ऑब्जेक्ट को addObserver:selector:name:object: विधि में पास करके उस अधिसूचना को पोस्ट करता है।

एप्पल समान स्थितियों में NSNotification का उपयोग करता है (UITextFieldTextDidBeginEditingNotification, UITextFieldTextDidChangeNotification, और UITextFieldTextDidEndEditingNotification सहित सूचनाएं UITextField के लिए परिभाषित किया, की तरह)।

+0

क्या आप मुझे बता सकते हैं कि क्या मैं इसका उपयोग कर रहा हूं? http://stackoverflow.com/questions/42111829/share-object-state-between-view-controllers-in-ios-development/42113389#42113389 –

-3

मैं कहता हूँ NSNotificationCenter हमेशा प्रतिनिधि मॉडल पर, इस्तेमाल किया जाना चाहिए, परिस्थितियों के अलावा जहां जानकारी (जैसे -webView:shouldLoadRequest:) पर एक प्रतिनिधि क्वेरी। यह लागू करने के लिए अधिक स्थिर, आसान है, और एक प्रतिनिधि का उपयोग करने की कोशिश कर क्लीनर कोड में परिणाम। दूसरा विकल्प ब्लॉक है, जो अच्छा हो सकता है, लेकिन जब स्मृति-प्रबंधन की बात आती है तो वे दर्द हो सकते हैं।

अंत में, यह आपके ऊपर है, लेकिन मुझे लगता है कि NSNotificationCenter लगभग किसी भी स्थिति में जाने का सबसे अच्छा तरीका है, अगर केवल एकाधिक पर्यवेक्षक कार्यक्षमता के लिए।

1

NSNotificationCenter आप जो सुझाव दे रहे हैं उसके लिए अधिक नहीं है, यह बिल्कुल सही समाधान है। यह मनाए गए ऑब्जेक्ट को अपने पर्यवेक्षकों के बारे में जानना या उनकी देखभाल करना रोकता है, जिससे आपका कोड अधिक ढीला और साफ हो जाता है।

अधिसूचना नामों के लिए स्ट्रिंग साझा करना मामूली है और उन्हें किसी साझा स्थिरांक फ़ाइल या मनाए गए ऑब्जेक्ट के शीर्षलेख में परिभाषित किया जा सकता है, यदि आपके पर्यवेक्षकों को अपनी कार्यवाही करने के लिए इस शीर्षलेख को आयात करने की आवश्यकता है।

0

ए-टू-एन प्रतिनिधि संबंध समझ में नहीं आता है।

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row 

उदाहरण के लिए देखें। क्या होगा यदि इस ऑब्जेक्ट में वास्तव में एन प्रतिनिधि थे? यह तय करना चाहिए कि अपने सभी प्रतिनिधियों से कौन से एन विचार वापस आते हैं? प्रतिनिधियों वास्तव में यह 1 से 1 सिद्धांत हैं।

NSNotificationCenter सही दृष्टिकोण है। सीधे शब्दों में का उपयोग

addObserver:selector:name:object: 

क्रमशः

postNotification: 

यह निश्चित रूप से बहुत ज्यादा कोड नहीं है। और यह आपके लिए बहुत आसान है क्योंकि केंद्र सभी कॉलों को संभालता है।

2

नोटिफिकेशन का उपयोग कर प्रसारण कर रहा है: 1 प्रेषक सिर्फ एक जानकारी भेजता है और जिसने कभी ट्यून किया है, उसे प्राप्त करता है। एक रेडियो स्टेशन की तरह बहुत कम, कोई चैनल वापस नहीं है (इस पल के लिए टेलीफ़ोन के बारे में भूल जाते हैं)

प्रतिनिधिमंडल कुछ अलग है। थ ऑब्जेक्ट, जो कुछ करने के लिए एक डिलीगेट से पूछता है, आमतौर पर उस अनुरोध के परिणाम की आवश्यकता होती है, वहां पूर्व प्रतिनिधिमंडल 1-से-1 संचार होता है, जिसे हमेशा वस्तु द्वारा शुरू किया जाता है, प्रतिनिधि नहीं (जबकि ऑब्जेक्ट में विधियां हो सकती हैं संचार शुरू करने के लिए ऑब्जेक्ट को सूचित करने के लिए कहा जा सकता है, यानी [tableView reloadData])।

तो अगर प्रेषक को डेटा वापस प्राप्त करने की आवश्यकता है, तो यह प्रतिनिधिमंडल है। यदि प्रेषक प्रसारण के बाद कुछ भी परवाह नहीं करता है, तो अधिसूचनाओं के साथ जाएं।

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

+0

आज मेरे पास केवल एक ऑब्जेक्ट होगा जो सभी वीसी साझा करते हैं और जो उन्हें सूचित करते हैं। – vikingosegundo

1

आपका प्रस्तावित समाधान NSNotificationCenter का उपयोग करने से न तो आसान है और न ही यह थ्रेड सुरक्षित है।

अपना समाधान थ्रेड सुरक्षित बनाने के लिए, आपको प्रतिनिधियों को सरणी को बदलने से रोकने के लिए एक तंत्र प्रदान करने की आवश्यकता होगी जबकि लूप के लिए ईवेंट प्रेषण चल रहा है।

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

अधिसूचना केंद्र का एक विकल्प कुंजी-मूल्य-निरीक्षण का उपयोग करना है यदि यह आपके उपयोग के मामलों की आवश्यकताओं को पूरा करता है।

आखिरकार, जिस तंत्र का आप उपयोग करने का निर्णय लेते हैं, इस पर निर्भर करता है कि यह आपके विशिष्ट उपयोग मामले पर सबसे अच्छा कैसे लागू होता है।

0

आप सिस्टम-व्यापी घटनाओं (जैसे कुंजीपटल की उपस्थिति या कुछ समान घटना) के अलावा किसी अन्य चीज़ के लिए NSNotificationCenter का उपयोग नहीं करना चाहते हैं। इसका कारण यह है कि यह पूरी तरह से टाइप-सुरक्षित नहीं है, सबकुछ सबकुछ पर निर्भर कर सकता है और आपको अब कोई संकलन समय चेक या उपयोग खोज परिणाम नहीं मिलते हैं।

मेरी राय में केवीओ को उस ऑब्जेक्ट के बाहर परिवर्तनों का निरीक्षण करने के लिए उपयोग नहीं किया जाना चाहिए, जिसके बाद आप इसे सुन रहे हैं क्योंकि इसमें समान पक्ष हैं (कोई संकलन समय जांच नहीं है, यदि आप श्रोताओं को ठीक से नहीं हटाते हैं या उन्हें दो बार पंजीकृत करते हैं) ।

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

हालांकि, मेरे BMCommons framework से कोड देखें जो इस समस्या को BMNullableArray और मैक्रोज़ का उपयोग करके अच्छी तरह से हल करता है। उन मैक्रो की परिभाषा के लिए BMCore.h हैडर देखें:

BM_LISTENER_METHOD_DECLARATION(protocol) 
BM_LISTENER_METHOD_IMPLEMENTATION(protocol) 

क्रियान्वयन सुनिश्चित करता है कि एक ही श्रोता दो बार और यह भी कि श्रोताओं दुर्बलता से रखा जाता है कभी नहीं जोड़ दिया जाएगा, किसी भी दुर्घटना वे पर खुद को अपंजीकृत कर भूल जाते हैं, भले ही कारण नहीं deallocation (हालांकि मैं इस शर्त को एक जोर से पकड़ना पसंद करता हूं क्योंकि यह एक प्रोग्रामिंग गलती है)।

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