ios - मैं उद्देश्य-सी में प्रतिनिधियों को कैसे बना सकता हूं?




objective-c cocoa callback delegates (17)

ऐप्पल द्वारा अनुशंसित एक अच्छी प्रैक्टिस के रूप में, यह NSObject प्रोटोकॉल के अनुरूप प्रतिनिधि के लिए अच्छा है (जो परिभाषा द्वारा प्रोटोकॉल है)।

@protocol MyDelegate <NSObject>
    ...
@end

और अपने प्रतिनिधि के भीतर वैकल्पिक तरीकों को बनाने के लिए (यानी विधियों को जरूरी नहीं है), आप इस तरह @optional एनोटेशन का उपयोग कर सकते हैं:

@protocol MyDelegate <NSObject>
    ...
    ...
      // Declaration for Methods that 'must' be implemented'
    ...
    ...
    @optional
    ...
      // Declaration for Methods that 'need not necessarily' be implemented by the class conforming to your delegate
    ...
@end

तो जब आप वैकल्पिक रूप से निर्दिष्ट विधियों का उपयोग करते हैं, तो आपको respondsToSelector (आपकी कक्षा में) की आवश्यकता होती है, respondsToSelector अगर चयन (जो आपके प्रतिनिधि के अनुरूप है) वास्तव में आपके वैकल्पिक तरीके को लागू किया गया है या नहीं।

मुझे पता है कि प्रतिनिधि कैसे काम करते हैं, और मुझे पता है कि मैं उनका उपयोग कैसे कर सकता हूं।

लेकिन मैं उन्हें कैसे बना सकता हूं?


ViewController.h

@protocol NameDelegate <NSObject>

-(void)delegateMEthod: (ArgType) arg;

@end

@property id <NameDelegate> delegate;

ViewController.m

[self.delegate delegateMEthod: argument];

MainViewController.m

ViewController viewController = [ViewController new];
viewController.delegate = self;

तरीका:

-(void)delegateMEthod: (ArgType) arg{
}

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

अगर मैं एक सी ++ / जावा प्रोग्रामर को प्रतिनिधियों को समझाता हूं तो मैं कहूंगा

प्रतिनिधियों क्या हैं? ये किसी अन्य वर्ग के भीतर कक्षाओं के लिए स्थिर संकेतक हैं। एक बार जब आप एक पॉइंटर असाइन करते हैं, तो आप उस वर्ग में फ़ंक्शंस / विधियों को कॉल कर सकते हैं। इसलिए आपकी कक्षा के कुछ कार्य "प्रतिनिधि" (सी ++ दुनिया में - एक क्लास ऑब्जेक्ट पॉइंटर द्वारा पॉइंटर) में किसी अन्य वर्ग में हैं।

प्रोटोकॉल क्या हैं? संकल्पनात्मक रूप से यह उस वर्ग के शीर्षलेख फ़ाइल के समान उद्देश्य के रूप में कार्य करता है जिसे आप एक प्रतिनिधि वर्ग के रूप में निर्दिष्ट कर रहे हैं। एक प्रोटोकॉल कक्षा को एक प्रतिनिधि के रूप में सेट करने वाले वर्ग में कौन से तरीकों को लागू करने की आवश्यकता है, इसे परिभाषित करने का एक स्पष्ट तरीका है।

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


मान लें कि आपके पास एक कक्षा है जिसे आपने विकसित किया है और कुछ प्रतिनिधि होने पर इसे सूचित करने में सक्षम होने के लिए एक प्रतिनिधि संपत्ति घोषित करना चाहते हैं:

@class myClass;

@protocol myClassDelegate <NSObject>

-(void)myClass:(MyClass*)myObject requiredEventHandlerWithParameter:(ParamType*)param;

@optional
-(void)myClass:(MyClass*)myObject optionalEventHandlerWithParameter:(ParamType*)param;

@end


@interface MyClass : NSObject

@property(nonatomic,weak)id< MyClassDelegate> delegate;

@end

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

आप यह भी देखेंगे कि प्रोटोकॉल विधियां MyClassDelegate इंस्टेंस को प्रतिनिधि के रूप में पैरामीटर के रूप में पास करती हैं, अगर प्रतिनिधि MyClassDelegate इंस्टेंस पर कुछ तरीकों को कॉल करना चाहता है तो यह सबसे अच्छा अभ्यास है और यह भी मदद करता है जब प्रतिनिधि खुद को MyClassDelegate रूप में कई MyClass उदाहरणों में घोषित करता है, जैसे जब आपके ViewController में एकाधिक UITableView's उदाहरण ViewController और आप सभी को UITableViewDelegate रूप में घोषित करते हैं।

और अपने MyClass अंदर आप प्रतिनिधि को घोषित घटनाओं के साथ सूचित करते हैं:

if([_delegate respondsToSelector:@selector(myClass: requiredEventHandlerWithParameter:)])
{
     [_delegate myClass:self requiredEventHandlerWithParameter:(ParamType*)param];
}

आप पहली बार जांचते हैं कि क्या आपका प्रतिनिधि प्रोटोकॉल विधि का जवाब देता है जिसे आप कॉल करने वाले हैं, यदि प्रतिनिधि इसे लागू नहीं करता है और ऐप तब क्रैश हो जाएगा (भले ही प्रोटोकॉल विधि आवश्यक हो)।


//1.
//Custom delegate 
@protocol TB_RemovedUserCellTag <NSObject>

-(void)didRemoveCellWithTag:(NSInteger)tag;

@end

//2.
//Create a weak reference in a class where you declared the delegate
@property(weak,nonatomic)id <TB_RemovedUserCellTag> removedCellTagDelegate;

//3. 
// use it in the class
  [self.removedCellTagDelegate didRemoveCellWithTag:self.tag];

//4. import the header file in the class where you want to conform to the protocol
@interface MyClassUsesDelegate ()<TB_RemovedUserCellTag>

@end

// 5। कक्षा में विधि को कार्यान्वित करें। एम - (शून्य) didRemoveCellWithTag: (एनएसआईएनटेगर) टैग {एनएसएलओजी @ ("टैग% डी", टैग);

}


ठीक है, यह वास्तव में प्रश्न का उत्तर नहीं है, लेकिन यदि आप देख रहे हैं कि अपना खुद का प्रतिनिधि कैसे बनाया जाए तो शायद आपके लिए कुछ बेहतर आसान हो सकता है।

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

NSNotification ऑब्जेक्ट्स को एक से अधिक प्राप्तकर्ताओं को पास कर सकता है और इसका उपयोग करना बहुत आसान है। यह इस तरह काम करता है:

MyClass.m फ़ाइल इस तरह दिखनी चाहिए

#import "MyClass.h"
@implementation MyClass 

- (void) myMethodToDoStuff {
//this will post a notification with myClassData (NSArray in this case)  in its userInfo dict and self as an object
[[NSNotificationCenter defaultCenter] postNotificationName:@"myClassUpdatedData"
                                                    object:self
                                                  userInfo:[NSDictionary dictionaryWithObject:selectedLocation[@"myClassData"] forKey:@"myClassData"]];
}
@end

किसी अन्य वर्ग में अपनी अधिसूचना का उपयोग करने के लिए: कक्षा को पर्यवेक्षक के रूप में जोड़ें:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(otherClassUpdatedItsData:) name:@"myClassUpdatedData" object:nil];

चयनकर्ता को लागू करें:

- (void) otherClassUpdatedItsData:(NSNotification *)note {
    NSLog(@"*** Other class updated its data ***");
    MyClass *otherClass = [note object];  //the object itself, you can call back any selector if you want
    NSArray *otherClassData = [note userInfo][@"myClassData"]; //get myClass data object and do whatever you want with it
}

यदि आपकी कक्षा को पर्यवेक्षक के रूप में निकालना न भूलें

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

अस्वीकरण: यह एक delegate बनाने के लिए Swift संस्करण है।

तो, प्रतिनिधियों क्या हैं? ... सॉफ्टवेयर विकास में, सामान्य पुन: प्रयोज्य समाधान आर्किटेक्चर हैं जो किसी दिए गए संदर्भ में सामान्य रूप से होने वाली समस्याओं को हल करने में मदद करते हैं, इसलिए इन "टेम्पलेट्स" को बोलने के लिए सबसे अच्छा डिजाइन पैटर्न के रूप में जाना जाता है। प्रतिनिधि एक डिज़ाइन पैटर्न होते हैं जो एक ऑब्जेक्ट को किसी अन्य ऑब्जेक्ट पर संदेश भेजने की अनुमति देता है जब कोई विशिष्ट घटना होती है। एक ऑब्जेक्ट की कल्पना करें ए ए ऑब्जेक्ट बी को एक्शन करने के लिए कॉल करता है। एक बार कार्रवाई पूरी होने के बाद, वस्तु ए को पता होना चाहिए कि बी ने कार्य पूरा कर लिया है और आवश्यक कार्रवाई कर ली है, इसे प्रतिनिधियों की मदद से हासिल किया जा सकता है!

एक बेहतर स्पष्टीकरण के लिए, मैं आपको एक कस्टम प्रतिनिधि बनाने का तरीका दिखाऊंगा जो कक्षाओं के बीच डेटा को पास करता है, स्विफ्ट के साथ एक साधारण एप्लिकेशन में, इस स्टार्टर प्रोजेक्ट को डाउनलोड या क्लोन करके शुरू करें और इसे चलाएं!

आप दो कक्षाओं, ViewController A और ViewController B साथ एक ऐप देख सकते हैं। बी में दो विचार हैं कि टैप पर ViewController का पृष्ठभूमि रंग बदलता है, कुछ भी जटिल नहीं है? अच्छी तरह से कक्षा ए के पृष्ठभूमि रंग को बदलने के एक आसान तरीके से सोचें जब कक्षा बी के विचार टैप किए जाते हैं।

समस्या यह है कि यह विचार कक्षा बी का हिस्सा हैं और कक्षा ए के बारे में कोई जानकारी नहीं है, इसलिए हमें इन दो वर्गों के बीच संवाद करने का एक तरीका ढूंढना होगा, और यही वह जगह है जहां प्रतिनिधिमंडल चमकता है। मैंने कार्यान्वयन को 6 चरणों में विभाजित किया ताकि आप इसे धोखाधड़ी के रूप में उपयोग कर सकें जब आपको इसकी आवश्यकता हो।

चरण 1: क्लासबीवीसी फ़ाइल में प्रोगमा मार्क चरण 1 की तलाश करें और इसे जोड़ें

//MARK: step 1 Add Protocol here.
protocol ClassBVCDelegate: class {
func changeBackgroundColor(_ color: UIColor?)
}

पहला कदम एक protocol बनाना है, इस मामले में, हम प्रोटोकॉल के अंदर कक्षा बी में प्रोटोकॉल बनाएंगे, आप अपने कार्यान्वयन की आवश्यकताओं के आधार पर जितना चाहें उतने कार्यों को बना सकते हैं। इस मामले में, हमारे पास एक साधारण कार्य है जो एक वैकल्पिक UIColor को तर्क के रूप में स्वीकार करता है। कक्षा के नाम के अंत में delegate को जोड़ने वाले प्रोटोकॉल को नाम देने का एक अच्छा अभ्यास है, इस मामले में, ClassBVCDelegate

चरण 2: ClassVBC में ClassVBC चिह्न चरण 2 की ClassVBC और इसे जोड़ें

//MARK: step 2 Create a delegate property here.
weak var delegate: ClassBVCDelegate?

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

चरण 3: क्लासबीवीसी में हैंडलटैप method अंदर प्रगमा चिह्न चरण 3 की ClassBVC और इसे जोड़ें

//MARK: step 3 Add the delegate method call here.
delegate?.changeBackgroundColor(tapGesture.view?.backgroundColor)

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

चरण 4: क्लासएवीसी में हैंडलटैप विधि के अंदर प्रोगमा मार्क चरण 4 की ClassAVC और इसे अपने क्लास प्रकार के आगे इस तरह जोड़ें।

//MARK: step 4 conform the protocol here.
class ClassAVC: UIViewController, ClassBVCDelegate {
}

अब क्लासएवीवी ने ClassBVCDelegate प्रोटोकॉल को अपनाया है, आप देख सकते हैं कि आपका कंपाइलर आपको एक त्रुटि दे रहा है जो कहता है कि "टाइप" क्लासएवीसी प्रोटोकॉल 'क्लासबीवीसीडीएगेट' के अनुरूप नहीं है और इसका मतलब यह है कि आपने अभी तक प्रोटोकॉल के तरीकों का उपयोग नहीं किया है, कल्पना करें जब कक्षा ए प्रोटोकॉल को गोद लेता है तो कक्षा बी के साथ अनुबंध पर हस्ताक्षर करना है और यह अनुबंध कहता है "मुझे अपनाए जाने वाले किसी भी वर्ग को मेरे कार्यों का उपयोग करना चाहिए!"

त्वरित नोट: यदि आप किसी Objective-C पृष्ठभूमि से आते हैं तो आप शायद सोच रहे हैं कि आप उस विधि को वैकल्पिक बनाने के लिए उस त्रुटि को भी बंद कर सकते हैं, लेकिन मेरे आश्चर्य के लिए, और शायद आपकी, Swift भाषा वैकल्पिक protocols समर्थन नहीं करती protocols , अगर आप चाहें ऐसा करें कि आप अपने protocol लिए एक एक्सटेंशन बना सकते हैं या अपने protocol कार्यान्वयन में @objc कीवर्ड का उपयोग कर सकते हैं।

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

यहां वैकल्पिक तरीकों के बारे में एक अच्छा लेख है।

चरण 5: सेगू विधि के लिए तैयार के अंदर प्रगमा चिह्न चरण 5 की तलाश करें और इसे जोड़ें

//MARK: step 5 create a reference of Class B and bind them through the `prepareforsegue` method.
if let nav = segue.destination as? UINavigationController, let classBVC = nav.topViewController as? ClassBVC {
classBVC.delegate = self
}

यहां हम केवल ClassBVC का एक उदाहरण बना रहे हैं और अपने प्रतिनिधि को स्वयं को सौंप सकते हैं, लेकिन यहां स्वयं क्या है? अच्छा, स्वयं ClassAVC जिसे प्रतिनिधिमंडल दिया गया है!

चरण 6: आखिरकार, ClassAVC में ClassAVC चरण 6 की ClassAVC और चलिए protocol के कार्यों का उपयोग करें, func change टाइप करना शुरू करें बैकग्राउंड रंग और आप देखेंगे कि यह आपके लिए स्वतः पूर्ण हो रहा है। आप इसके अंदर कोई कार्यान्वयन जोड़ सकते हैं, इस उदाहरण में, हम केवल पृष्ठभूमि रंग बदल देंगे, इसे जोड़ें।

//MARK: step 6 finally use the method of the contract
func changeBackgroundColor(_ color: UIColor?) {
view.backgroundColor = color
}

अब ऐप चलाएं!

Delegates हर जगह हैं और आप शायद उन्हें बिना किसी सूचना के इस्तेमाल करते हैं, अगर आप अतीत में एक UIKIT बनाते हैं तो आप प्रतिनिधिमंडल का इस्तेमाल करते हैं, UIKIT कई वर्ग उनके आसपास काम करते हैं और कई अन्य frameworks भी काम करते हैं, वे इन मुख्य समस्याओं को हल करते हैं।

  • वस्तुओं के तंग युग्मन से बचें।
  • ऑब्जेक्ट्स को उप-वर्ग की आवश्यकता के बिना व्यवहार और उपस्थिति को संशोधित करें।
  • किसी भी मनमानी वस्तु को कार्यों को संभालने की अनुमति दें।

बधाई हो, आप सिर्फ एक कस्टम प्रतिनिधि को लागू करते हैं, मुझे पता है कि आप शायद सोच रहे हैं, इस के लिए इतना परेशानी है? अच्छा, प्रतिनिधिमंडल यह समझने के लिए एक बहुत ही महत्वपूर्ण डिजाइन पैटर्न है कि आप iOS डेवलपर बनना चाहते हैं, और हमेशा ध्यान रखें कि उनके पास वस्तुओं के बीच एक से एक संबंध है।

आप here मूल ट्यूटोरियल देख सकते हैं


प्रतिनिधि बनाने के लिए यहां एक आसान तरीका है

.h फ़ाइल में प्रोटोकॉल बनाएं। सुनिश्चित करें कि @class का उपयोग करते हुए प्रोटोकॉल से पहले UIViewController के नाम से परिभाषित किया गया है < As the protocol I am going to use is UIViewController class>.

चरण: 1: "YourViewController" नामक एक नया वर्ग प्रोटोकॉल बनाएं जो UIViewController क्लास का उप-वर्ग होगा और इस क्लास को दूसरे व्यू कंट्रोलर को असाइन करेगा।

चरण: 2: "YourViewController" फ़ाइल पर जाएं और इसे नीचे के रूप में संशोधित करें:

#import <UIKit/UIkit.h>
@class YourViewController;

@protocol YourViewController Delegate <NSObject>

 @optional
-(void)defineDelegateMethodName: (YourViewController *) controller;

@required
-(BOOL)delegateMethodReturningBool: (YourViewController *) controller;

  @end
  @interface YourViewController : UIViewController

  //Since the property for the protocol could be of any class, then it will be marked as a type of id.

  @property (nonatomic, weak) id< YourViewController Delegate> delegate;

@end

प्रोटोकॉल व्यवहार में परिभाषित विधियों को प्रोटोकॉल परिभाषा के हिस्से के रूप में @optional और @required के साथ नियंत्रित किया जा सकता है।

चरण: 3: प्रतिनिधि का कार्यान्वयन

    #import "delegate.h"

   @interface YourDelegateUser ()
     <YourViewControllerDelegate>
   @end

   @implementation YourDelegateUser

   - (void) variousFoo {
      YourViewController *controller = [[YourViewController alloc] init];
      controller.delegate = self;
   }

   -(void)defineDelegateMethodName: (YourViewController *) controller {
      // handle the delegate being called here
   }

   -(BOOL)delegateMethodReturningBool: (YourViewController *) controller {
      // handle the delegate being called here
      return YES;
   }

   @end

// परीक्षण करें कि इसे कॉल करने से पहले विधि को परिभाषित किया गया है या नहीं

 - (void) someMethodToCallDelegate {
     if ([[self delegate] respondsToSelector:@selector(defineDelegateMethodName:)]) {
           [self.delegate delegateMethodName:self]; 
     }
  }

उत्तर वास्तव में उत्तर दिया जाता है, लेकिन मैं आपको एक प्रतिनिधि बनाने के लिए "धोखा शीट" देना चाहता हूं:

DELEGATE SCRIPT

CLASS A - Where delegate is calling function

@protocol <#Protocol Name#> <NSObject>

-(void)delegateMethod;

@end

@interface <#Some ViewController#> : <#UIViewController#> 

@property (nonatomic, assign) id <<#Protocol Name#>> delegate;

@end


@implementation <#Some ViewController#> 

-(void)someMethod {
    [self.delegate methodName];
}

@end




CLASS B - Where delegate is called 

@interface <#Other ViewController#> (<#Delegate Name#>) {}
@end

@implementation <#Other ViewController#> 

-(void)otherMethod {
    CLASSA *classA = [[CLASSA alloc] init];

    [classA setDelegate:self];
}

-delegateMethod() {

}

@end

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

उदाहरण के लिए, मान लें कि आपके पास UIWebView । यदि आप अपने प्रतिनिधि के webViewDidStartLoad: विधि को कार्यान्वित करना चाहते हैं, तो आप इस तरह की कक्षा बना सकते हैं:

@interface MyClass<UIWebViewDelegate>
// ...
@end

@implementation MyClass
- (void)webViewDidStartLoad:(UIWebView *)webView { 
    // ... 
}
@end

फिर आप MyClass का एक उदाहरण बना सकते हैं और इसे वेब व्यू के प्रतिनिधि के रूप में असाइन कर सकते हैं:

MyClass *instanceOfMyClass = [[MyClass alloc] init];
myWebView.delegate = instanceOfMyClass;

UIWebView पक्ष पर, संभवतः यह देखने के लिए कोड समान होता है कि प्रतिनिधि webViewDidStartLoad: का respondsToSelector: का उपयोग कर संदेश webViewDidStartLoad: respondsToSelector: और उचित होने पर इसे भेजें।

if([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
    [self.delegate webViewDidStartLoad:self];
}

प्रतिनिधि संपत्ति को आम तौर पर weak लूप से बचने के लिए weak घोषित किया जाता है (एआरसी में) या assign (प्री-एआरसी), क्योंकि ऑब्जेक्ट के प्रतिनिधि अक्सर उस ऑब्जेक्ट का मजबूत संदर्भ रखते हैं। (उदाहरण के लिए, एक व्यू कंट्रोलर प्रायः एक दृश्य का प्रतिनिधि होता है।)

अपनी कक्षाओं के लिए प्रतिनिधि बनाना

अपने स्वयं के प्रतिनिधियों को परिभाषित करने के लिए, आपको प्रोटोकॉल पर ऐप्पल डॉक्स में चर्चा के अनुसार कहीं भी अपनी विधियों की घोषणा करनी होगी। आप आमतौर पर एक औपचारिक प्रोटोकॉल घोषित करते हैं। UIWebView.h से उल्लिखित घोषणा, इस तरह दिखेगी:

@protocol UIWebViewDelegate <NSObject>
@optional
- (void)webViewDidStartLoad:(UIWebView *)webView;
// ... other methods here
@end

यह एक इंटरफेस या अमूर्त बेस क्लास के समान है, क्योंकि यह इस मामले में आपके प्रतिनिधि, UIWebViewDelegate लिए एक विशेष प्रकार बनाता है। प्रतिनिधियों को इस प्रोटोकॉल को अपनाना होगा:

@interface MyClass <UIWebViewDelegate>
// ...
@end

और फिर प्रोटोकॉल में विधियों को लागू करें। प्रोटोकॉल में @optional (अधिकांश प्रतिनिधि विधियों की तरह) के रूप में घोषित विधियों के लिए, आपको इसके बारे में एक विशेष विधि कॉल करने से पहले, इसके साथ-साथ -respondsToSelector: जांच करने की आवश्यकता है।

नामकरण

प्रतिनिधि विधियों को आम तौर पर प्रतिनिधि वर्ग के नाम से शुरू किया जाता है, और प्रतिनिधि वस्तु को पहले पैरामीटर के रूप में लेते हैं। वे अक्सर एक इच्छा, चाहिए, या किया-रूप का उपयोग करते हैं। तो, webViewDidStartLoad: उदाहरण के लिए loadStarted (कोई पैरामीटर नहीं लेना) के बजाय (पहला पैरामीटर वेब दृश्य है)।

गति अनुकूलन

यह जांचने के बजाय कि जब कोई प्रतिनिधि इसे संदेश भेजना चाहता है तो कोई प्रतिनिधि किसी चयनकर्ता को जवाब देता है, तो प्रतिनिधि सेट होने पर आप उस जानकारी को कैश कर सकते हैं। ऐसा करने का एक बहुत ही साफ तरीका निम्न प्रकार के बिटफील्ड का उपयोग करना है:

@protocol SomethingDelegate <NSObject>
@optional
- (void)something:(id)something didFinishLoadingItem:(id)item;
- (void)something:(id)something didFailWithError:(NSError *)error;
@end

@interface Something : NSObject
@property (nonatomic, weak) id <SomethingDelegate> delegate;
@end

@implementation Something {
  struct {
    unsigned int didFinishLoadingItem:1;
    unsigned int didFailWithError:1;
  } delegateRespondsTo;
}
@synthesize delegate;

- (void)setDelegate:(id <SomethingDelegate>)aDelegate {
  if (delegate != aDelegate) {
    delegate = aDelegate;

    delegateRespondsTo.didFinishLoadingItem = [delegate respondsToSelector:@selector(something:didFinishLoadingItem:)];
    delegateRespondsTo.didFailWithError = [delegate respondsToSelector:@selector(something:didFailWithError:)];
  }
}
@end

फिर, शरीर में, हम जांच सकते हैं कि हमारे प्रतिनिधि हमारे प्रेषक को एक्सेस करके संदेशों को संभालते हैं, प्रेषण करने के बजाय, प्रेषक द्वारा -respondsToSelector: बार-बार -respondsToSelector: बार-बार।

अनौपचारिक प्रतिनिधि

प्रोटोकॉल अस्तित्व से पहले, NSObject पर एक category का उपयोग करना आम तौर पर एक प्रतिनिधि लागू करने के तरीकों की घोषणा करना आम था। उदाहरण के लिए, CALayer अभी भी यह करता है:

@interface NSObject(CALayerDelegate)
- (void)displayLayer:(CALayer *)layer;
// ... other methods here
@end

यह अनिवार्य रूप से संकलक को बताता है कि कोई ऑब्जेक्ट displayLayer: लागू कर सकता है:।

फिर आप इस विधि को कॉल करने के लिए उपरोक्त वर्णित दृष्टिकोण के समान -respondsToSelector: उपयोग करेंगे। प्रतिनिधियों ने बस इस विधि को लागू किया है और delegate संपत्ति असाइन की है, और यह है (आप प्रोटोकॉल के अनुरूप कोई घोषणा नहीं कर रहे हैं)। यह विधि ऐप्पल के पुस्तकालयों में आम है, लेकिन नए कोड को ऊपर के अधिक आधुनिक प्रोटोकॉल दृष्टिकोण का उपयोग करना चाहिए, क्योंकि यह दृष्टिकोण एनएसओब्जेक्ट को प्रदूषित करता है (जो स्वत: पूर्ण कम उपयोगी बनाता है) और कंपाइलर को टाइपो और इसी तरह की त्रुटियों के बारे में आपको चेतावनी देना मुश्किल बनाता है।


Let's start with an example , if we buy a product online ,it goes through process like shipping/delivery handled by different teams.So if shipping gets completed ,shipping team should notify delivery team & it should be one to one communication as broadcasting this information would be overhead for other people / vendor might want to pass this information only to required people.

So if we think in terms of our app, an event can be an online order & different teams can be like multiple views.

यहां कोड शिपिंग शिपिंग को डिलीवरी टीम के रूप में शिपिंग टीम और डिलिवरी व्यू के रूप में माना जाता है:

//Declare the protocol with functions having info which needs to be communicated
protocol ShippingDelegate : class {
    func productShipped(productID : String)
}
//shippingView which shows shipping status of products
class ShippingView : UIView
{

    weak var delegate:ShippingDelegate?
    var productID : String

    @IBAction func checkShippingStatus(sender: UIButton)
    {
        // if product is shipped
        delegate?.productShipped(productID: productID)
    }
}
//Delivery view which shows delivery status & tracking info
class DeliveryView: UIView,ShippingDelegate
{
    func productShipped(productID : String)
    {
        // update status on view & perform delivery
    }
}

//Main page on app which has both views & shows updated info on product whole status
class ProductViewController : UIViewController
{
    var shippingView : ShippingView
    var deliveryView : DeliveryView

    override func viewDidLoad() {
        super.viewDidLoad()
        // as we want to update shipping info on delivery view, so assign delegate to delivery object
        // whenever shipping status gets updated it will call productShipped method in DeliveryView & update UI.
        shippingView.delegate = deliveryView
        //
    }
}

मेरे दृष्टिकोण में उस प्रतिनिधि विधि के लिए अलग वर्ग बनाएं और आप जहां चाहें इसका उपयोग कर सकते हैं।

मेरे कस्टम DropDownClass.h में

typedef enum
{
 DDSTATE,
 DDCITY
}DropDownType;

@protocol DropDownListDelegate <NSObject>
@required
- (void)dropDownDidSelectItemWithString:(NSString*)itemString     DropDownType:(DropDownType)dropDownType;
@end
@interface DropDownViewController : UIViewController
{
 BOOL isFiltered;
}
@property (nonatomic, assign) DropDownType dropDownType;
@property (weak) id <DropDownListDelegate> delegate;
@property (strong, nonatomic) NSMutableArray *array1DropDown;
@property (strong, nonatomic) NSMutableArray *array2DropDown;

उस .m फ़ाइल के बाद वस्तुओं के साथ सरणी बनाते हैं,

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
CGFloat rowHeight = 44.0f;
return rowHeight;
}

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return isFiltered?[self.array1DropDown count]:[self.array2DropDown count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = @"TableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}

if (self.delegate) {
    if (self.dropDownType == DDCITY) {
        cell.textLabel.text = [self.array1DropDown objectAtIndex:indexPath.row];
    }
    else if (self.dropDownType == DDSTATE) {
        cell.textLabel.text = [self.array2DropDown objectAtIndex:indexPath.row];
    }
}
return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
 [self dismissViewControllerAnimated:YES completion:^{
    if(self.delegate){
        if(self.dropDownType == DDCITY){
            [self.delegate dropDownDidSelectItemWithString:[self.array1DropDown objectAtIndex:indexPath.row] DropDownType:self.dropDownType];
        }
        else if (self.dropDownType == DDSTATE) {
            [self.delegate dropDownDidSelectItemWithString:[self.array2DropDown objectAtIndex:indexPath.row] DropDownType:self.dropDownType];
        }
    }
}];
}

Here all are set for Custom delegate class.after that you can use this delegate method where you want.for example...

in my another viewcontroller import after that

create action for calling delegate method like this

- (IBAction)dropDownBtn1Action:(id)sender {
DropDownViewController *vehicleModelDropView = [[DropDownViewController alloc]init];
vehicleModelDropView.dropDownType = DDCITY;
vehicleModelDropView.delegate = self;
[self presentViewController:vehicleModelDropView animated:YES completion:nil];
}

after that call delegate method like this

- (void)dropDownDidSelectItemWithString:(NSString *)itemString DropDownType:(DropDownType)dropDownType {
switch (dropDownType) {
    case DDCITY:{
        if(itemString.length > 0){
            //Here i am printing the selected row
            [self.dropDownBtn1 setTitle:itemString forState:UIControlStateNormal];
        }
    }
        break;
    case DDSTATE: {
        //Here i am printing the selected row
        [self.dropDownBtn2 setTitle:itemString forState:UIControlStateNormal];
    }

    default:
        break;
}
}

प्रतिनिधि: - बनाएँ

@protocol addToCartDelegate <NSObject>

-(void)addToCartAction:(ItemsModel *)itemsModel isAdded:(BOOL)added;

@end

भेजें और कृपया डेटा भेजने के लिए प्रतिनिधि को असाइन करें

[self.delegate addToCartAction:itemsModel isAdded:YES];

अनुमोदित उत्तर बहुत अच्छा है, लेकिन यदि आप 1 मिनट के उत्तर की तलाश में हैं तो इसे आजमाएं:

MyClass.h फ़ाइल इस तरह दिखनी चाहिए (टिप्पणी के साथ प्रतिनिधि लाइन जोड़ें!)

#import <BlaClass/BlaClass.h>

@class MyClass;             //define class, so protocol can see MyClass
@protocol MyClassDelegate <NSObject>   //define delegate protocol
    - (void) myClassDelegateMethod: (MyClass *) sender;  //define delegate method to be implemented within another class
@end //end protocol

@interface MyClass : NSObject {
}
@property (nonatomic, weak) id <MyClassDelegate> delegate; //define MyClassDelegate as delegate

@end

MyClass.m फ़ाइल इस तरह दिखनी चाहिए

#import "MyClass.h"
@implementation MyClass 
@synthesize delegate; //synthesise  MyClassDelegate delegate

- (void) myMethodToDoStuff {
    [self.delegate myClassDelegateMethod:self]; //this will call the method implemented in your other class    
}

@end

किसी अन्य वर्ग में अपने प्रतिनिधि का उपयोग करने के लिए (UIViewController इस मामले में MyVC कहा जाता है) MyVC.h:

#import "MyClass.h"
@interface MyVC:UIViewController <MyClassDelegate> { //make it a delegate for MyClassDelegate
}

MyVC.m:

myClass.delegate = self;          //set its delegate to self somewhere

प्रतिनिधि विधि लागू करें

- (void) myClassDelegateMethod: (MyClass *) sender {
    NSLog(@"Delegates are great!");
}

कृप्या! आईओएस में प्रतिनिधि कैसे काम करता है यह समझने के लिए चरणबद्ध ट्यूटोरियल द्वारा सरल चरण नीचे देखें।

आईओएस में प्रतिनिधि

मैंने दो व्यू कंट्रोलर बनाए हैं (एक से दूसरे डेटा भेजने के लिए)

  1. FirstViewController प्रतिनिधि को लागू करें (जो डेटा प्रदान करता है)।
  2. SecondViewController प्रतिनिधि को घोषित करें (जो डेटा प्राप्त करेगा)।

प्रतिनिधि समर्थन बनाने के लिए औपचारिक प्रोटोकॉल विधि का उपयोग करते समय, मैंने पाया है कि आप कुछ प्रकार जोड़कर उचित प्रकार की जांच (हालांकि, रनटाइम, संकलन समय नहीं) सुनिश्चित कर सकते हैं:

if (![delegate conformsToProtocol:@protocol(MyDelegate)]) {
    [NSException raise:@"MyDelegate Exception"
                format:@"Parameter does not conform to MyDelegate protocol at line %d", (int)__LINE__];
}

अपने प्रतिनिधि एक्सेसर (setDelegate) कोड में। यह गलतियों को कम करने में मदद करता है।


केवल चयनकर्ता के साथ फ़ाइल में त्रुटि को अनदेखा करने के लिए, निम्नानुसार एक #pragma जोड़ें:

#pragma clang diagnostic ignored "-Warc-performSelector-leaks"

यह इस लाइन पर चेतावनी को अनदेखा कर देगा, लेकिन फिर भी इसे आपके बाकी प्रोजेक्ट में अनुमति देता है।





ios objective-c cocoa callback delegates