मैं कैसे प्रतिनिधियों काम जानते हैं, और मैं जानता हूँ कि मैं उन्हें कैसे उपयोग कर सकते हैं।
लेकिन मैं उन्हें कैसे बना सकता हूँ?
मैं कैसे प्रतिनिधियों काम जानते हैं, और मैं जानता हूँ कि मैं उन्हें कैसे उपयोग कर सकते हैं।
लेकिन मैं उन्हें कैसे बना सकता हूँ?
एक ऑब्जेक्टिव-सी प्रतिनिधि एक वस्तु है कि करने के लिए असाइन किया गया है 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:और उचित होने पर भेज सकते हैं।
if([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
[self.delegate webViewDidStartLoad:self];
}
प्रतिनिधि संपत्ति ही आम तौर पर घोषित किया जाता है weak(एआरसी में) या assign(पूर्व एआरसी) छोरों को बनाए रखने से बचने के लिए, के बाद से एक वस्तु का प्रतिनिधि अक्सर उस वस्तु के लिए एक मजबूत संदर्भ रखती है। (उदाहरण के लिए, एक दृश्य नियंत्रक अक्सर एक दृश्य यह होता है की प्रतिनिधि है।)
अपने खुद के प्रतिनिधियों को परिभाषित करने के लिए, आप के रूप में में चर्चा कहीं उनके तरीकों घोषित करने के लिए, होगा प्रोटोकॉल पर एप्पल डॉक्स । आप आम तौर पर एक औपचारिक प्रोटोकॉल घोषणा करते हैं। घोषणा, UIWebView.h से दूसरे शब्दों में बयान, इस प्रकार दिखाई देगा:
@protocol UIWebViewDelegate <NSObject>
@optional
- (void)webViewDidStartLoad:(UIWebView *)webView;
// ... other methods here
@end
यह एक इंटरफ़ेस या अमूर्त आधार वर्ग के अनुरूप है के रूप में यह, आपका प्रतिनिधि के लिए एक विशेष प्रकार बनाता है UIWebViewDelegateइस मामले में। प्रतिनिधि कार्यान्वयन इस प्रोटोकॉल को अपनाने के लिए होगा:
@interface MyClass <UIWebViewDelegate>
// ...
@end
और फिर प्रोटोकॉल में तरीकों को लागू। विधियों के रूप में प्रोटोकॉल में घोषित लिए @optional(सबसे प्रतिनिधि तरीकों की तरह), आप के साथ जांच करने की आवश्यकता -respondsToSelector:पर एक विशेष विधि कॉल करने से पहले।
प्रतिनिधि तरीकों आम तौर पर delegating वर्ग के नाम के साथ शुरू नाम है, और पहले पैरामीटर के रूप delegating वस्तु ले रहे हैं। उन्होंने यह भी अक्सर एक, will- should-, या did- फार्म का उपयोग करें। तो, webViewDidStartLoad:बजाय (पहले पैरामीटर वेब दृश्य है) loadStarted(उदाहरण के लिए कोई पैरामीटर लेने)।
जाँच एक प्रतिनिधि एक चयनकर्ता को हर बार जब हम यह संदेश भेजना चाहते हैं जवाब देती है या करने के बजाय, आप उस जानकारी को कैश कर सकते जब प्रतिनिधियों सेट कर रहे हैं। इस प्रकार यह करने के लिए एक बहुत साफ तरीके से, एक bitfield उपयोग करने के लिए है:
@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
फिर, शरीर में, हम देख सकते हैं कि हमारे प्रतिनिधि हमारे एक्सेस करके संदेशों को संभालती है delegateRespondsTo, बजाय भेजकर struct -respondsToSelector:बार बार।
इससे पहले कि प्रोटोकॉल से ही अस्तित्व में है, यह एक का उपयोग एक आम बात थी श्रेणी पर NSObjectतरीकों एक प्रतिनिधि को लागू कर सकता है की घोषणा करने के। उदाहरण के लिए, CALayerअभी भी इस करता है:
@interface NSObject(CALayerDelegate)
- (void)displayLayer:(CALayer *)layer;
// ... other methods here
@end
यह अनिवार्य रूप से संकलक कि किसी भी वस्तु को लागू कर सकते हैं बताता है displayLayer:।
फिर आप उसी का प्रयोग करेंगे -respondsToSelector:जैसा कि ऊपर वर्णित इस विधि कॉल करने के लिए दृष्टिकोण। प्रतिनिधियों बस इस विधि को लागू करने और आवंटित delegateसंपत्ति, और बस हो गया (कोई आप एक प्रोटोकॉल के अनुरूप की घोषणा नहीं है)। इस विधि एप्पल के पुस्तकालयों में आम है, लेकिन नए कोड के ऊपर और अधिक आधुनिक प्रोटोकॉल दृष्टिकोण का उपयोग करना चाहिए, के बाद से इस दृष्टिकोण pollutes NSObject(जो स्वत: पूर्ण कम उपयोगी बनाता है) और यह मुश्किल संकलक लिखने की त्रुटियों और इसी तरह की त्रुटियों के बारे में चेतावनी देने के लिए बन जाता है।
अनुमोदित जवाब महान है, लेकिन यह कोशिश आप एक 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!");
}
प्रतिनिधि समर्थन बनाने के लिए औपचारिक प्रोटोकॉल विधि का उपयोग करते हैं, तो मैं पाया है कि आप उचित प्रकार की तरह कुछ जोड़कर जाँच (यद्यपि, क्रम, नहीं समय संकलन) यह सुनिश्चित कर सकते हैं:
if (![delegate conformsToProtocol:@protocol(MyDelegate)]) {
[NSException raise:@"MyDelegate Exception"
format:@"Parameter does not conform to MyDelegate protocol at line %d", (int)__LINE__];
}
आपका प्रतिनिधि एक्सेसर (setDelegate) कोड में। यह गलतियों को कम करने में मदद करता है।
हो सकता है कि इस बात का है कि तुम क्या याद कर रहे हैं लाइनों के साथ अधिक है:
आप एक सी ++ की तरह दृष्टिकोण से आ रहे हैं, प्रतिनिधियों लेता है एक छोटे से करने के लिए इस्तेमाल हो रही है - लेकिन मूल रूप से 'वे सिर्फ काम'।
जिस तरह से यह काम करता है आप एक या कई संभावित प्रतिनिधि तरीकों में से कुछ के लिए कुछ उद्देश्य यह है कि आप NSWindow के प्रतिनिधि के रूप में लिखा था द्वारा सेट किए गए हैं, लेकिन अपने वस्तु केवल कार्यान्वयन (विधि) है। तो कुछ होता है, और NSWindowअपने ऑब्जेक्ट कॉल करने के लिए चाहता है - यह सिर्फ ऑब्जेक्टिव-सी के उपयोग करता है respondsToSelectorनिर्धारित करें कि आपका उद्देश्य यह है कि विधि कहा जाता है चाहता विधि, और फिर इसे कहते हैं। इस तरह ऑब्जेक्टिव-सी काम करता है - तरीकों मांग पर देखा जाता है।
यह विशेष चल रहा कोई बात नहीं है पूरी तरह से अपनी खुद की वस्तुओं के साथ यह करने के लिए तुच्छ है, तो आप उदाहरण के लिए एक हो सकता है NSArray27 वस्तुओं की, वस्तुओं के सभी विभिन्न प्रकार के केवल 18 उनमें से कुछ विधि होने -(void)setToBue;अन्य 9 नहीं है। तो कॉल करने के लिए setToBlue18 के सभी पर जरूरत है कि यह किया, कुछ इस तरह:
for (id anObject in myArray)
{
if ([anObject respondsToSelector:@selector(@"setToBlue")])
[anObject setToBlue];
}
प्रतिनिधियों के बारे में दूसरी बात यह है कि वे, बने नहीं रहते हैं, ताकि आप हमेशा के लिए प्रतिनिधि सेट करने के लिए है nilअपने में MyClass deallocविधि।
कृप्या! कदम ट्यूटोरियल द्वारा सरल कदम नीचे की जाँच को समझने के लिए प्रतिनिधियों आईओएस में काम करता है।
मैं (एक से दूसरे डेटा भेजने के लिए) दो ViewControllers बनाया है
एप्पल द्वारा की सिफारिश की एक अच्छा अभ्यास के रूप में, यह के अनुरूप प्रतिनिधि (जो एक प्रोटोकॉल है, परिभाषा के द्वारा) के लिए अच्छा है, 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अगर दृश्य (है कि अपने प्रतिनिधि के अनुरूप किया जाता है) वास्तव में अपने वैकल्पिक विधि (एस) या नहीं लागू किया गया है।
मुझे लगता है कि इन सभी प्रश्नों के उत्तर भावना का एक बहुत बनाने के एक बार आप प्रतिनिधियों को समझते हैं। व्यक्तिगत तौर पर मैं C / C की भूमि से ++ और फोरट्रान आदि इसलिए यहाँ मेरी 2 मिनट सी ++ प्रतिमान में समान analogues खोजने पर ले की तरह है कि प्रक्रियात्मक भाषाओं से पहले आया था।
अगर मैं एक सी ++ / जावा प्रोग्रामर के प्रतिनिधियों की व्याख्या करने के लिए गए थे मैं कहूंगा
प्रतिनिधियों क्या हैं? ये एक और वर्ग के भीतर वर्गों के लिए स्थिर संकेत दिए गए हैं। एक बार जब आप एक सूचक असाइन करते हैं, आपको लगता है कि कक्षा में कार्य / तरीकों कॉल कर सकते हैं। एक और वर्ग के लिए - (एक वर्ग वस्तु सूचक द्वारा करने के लिए सूचक सी ++ दुनिया में) इसलिए अपने वर्ग के कुछ कार्यों "नियुक्त" कर रहे हैं।
प्रोटोकॉल क्या हैं? सैद्धांतिक रूप से यह वर्ग आप एक प्रतिनिधि के वर्ग के रूप में बताए जाते हैं के हेडर फाइल के रूप में के रूप में इसी तरह के उद्देश्य में कार्य करता। एक प्रोटोकॉल को परिभाषित क्या तरीकों वर्ग कौन है सूचक एक वर्ग के भीतर एक प्रतिनिधि के रूप स्थापित किया गया था में लागू किए जाने की आवश्यकता का एक स्पष्ट तरीका है।
मैं सी ++ में कुछ इसी तरह कैसे कर सकता है? आप सी ++ में ऐसा करने की कोशिश की, तो आप वर्ग परिभाषा वर्गों (वस्तुओं) की ओर इशारा परिभाषित करने और फिर से उन्हें तारों हैं अन्य वर्गों है कि अपने आधार वर्ग के प्रतिनिधियों के रूप में अतिरिक्त कार्य प्रदान करेगा करने के लिए। लेकिन इस तारों कोड के भीतर maitained की जरूरत है और अनाड़ी हो सकता है और प्रवण त्रुटि होगा। उद्देश्य सी बस मानता है कि प्रोग्रामर इस decipline बनाए रखने में नहीं सबसे अच्छा कर रहे हैं और एक साफ कार्यान्वयन लागू करने के लिए संकलक प्रतिबंध प्रदान करता है।
एक प्रतिनिधि सिर्फ एक वर्ग है कि एक और वर्ग के लिए कुछ काम करता है। कुछ हद तक एक मूर्ख (लेकिन उम्मीद है कि शिक्षाप्रद) खेल का मैदान उदाहरण यह कैसे स्विफ्ट में किया जाता है पता चलता है कि के लिए निम्न कोड पढ़ें।
// A protocol is just a list of methods (and/or properties) that must
// be used by any class that adopts the protocol.
protocol OlderSiblingDelegate: class {
// This protocol only defines one required method
func getYourNiceOlderSiblingAGlassOfWater() -> String
}
class BossyBigBrother {
// The delegate is the BossyBigBrother's slave. This position can
// be assigned later to whoever is available (and conforms to the
// protocol).
weak var delegate: OlderSiblingDelegate?
func tellSomebodyToGetMeSomeWater() -> String? {
// The delegate is optional because there might not be anyone
// nearby to boss around.
return delegate?.getYourNiceOlderSiblingAGlassOfWater()
}
}
// PoorLittleSister conforms to the OlderSiblingDelegate protocol
class PoorLittleSister: OlderSiblingDelegate {
// This method is repquired by the protocol, but the protocol said
// nothing about how it needs to be implemented.
func getYourNiceOlderSiblingAGlassOfWater() -> String {
return "Go get it yourself!"
}
}
// initialize the classes
let bigBro = BossyBigBrother()
let lilSis = PoorLittleSister()
// Set the delegate
// bigBro could boss around anyone who conforms to the
// OlderSiblingDelegate protocol, but since lilSis is here,
// she is the unlucky choice.
bigBro.delegate = lilSis
// Because the delegate is set, there is a class to do bigBro's work for him.
// bigBro tells lilSis to get him some water.
if let replyFromLilSis = bigBro.tellSomebodyToGetMeSomeWater() {
print(replyFromLilSis) // "Go get it yourself!"
}
वास्तविक व्यवहार में, प्रतिनिधियों अक्सर निम्न स्थितियों में किया जाता है
कक्षाओं को छोड़कर प्रतिनिधि वर्ग के लिए आवश्यक प्रोटोकॉल के अनुरूप है कि एक दूसरे को पहले के बारे में कुछ भी जानने की जरूरत नहीं है।
मैं अत्यधिक निम्नलिखित दो लेख पढ़ने की सलाह देते हैं। उन्होंने मुझे और भी बेहतर की तुलना में प्रतिनिधियों को समझने में मदद प्रलेखन किया था।
मान लीजिए कि आपने एक वर्ग है कि आप विकसित किया है और एक प्रतिनिधि संपत्ति घोषित करने के लिए यह सूचित करने के लिए जब किसी घटना होता है सक्षम होना चाहते हैं:
@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उदाहरण इसलिए यदि आप प्रतिनिधि के रूप में बनाए रखने के लिए, उन दोनों को एक दूसरे के और न रख सकेंगे घोषित उनमें से कभी जारी किया जाएगा)।
तुम भी है कि प्रोटोकॉल तरीकों से गुजरता देखेंगे MyClassपैरामीटर के रूप में प्रतिनिधि के लिए उदाहरण के लिए, इस मामले में सबसे अच्छा अभ्यास है प्रतिनिधि पर कुछ तरीकों कॉल करना चाहते हैं MyClassउदाहरण है और यह भी मदद करता है जब प्रतिनिधि के रूप में खुद को वाणी MyClassDelegateकई करने के लिए MyClassउदाहरण हैं, जैसे जब आप एक से अधिक है UITableView'sअपने में उदाहरणों ViewControllerऔर एक के रूप में खुद वाणी UITableViewDelegateउन सभी को।
और अपने अंदर MyClassआप इस प्रकार की घोषणा की घटनाओं के साथ प्रतिनिधि सूचित करें:
if([_delegate respondsToSelector:@selector(myClass: requiredEventHandlerWithParameter:)])
{
[_delegate myClass:self requiredEventHandlerWithParameter:(ParamType*)param];
}
आप पहले जांच आपका प्रतिनिधि प्रोटोकॉल विधि है कि आप के बारे में मामले में कॉल करने के लिए प्रतिनिधि इसे लागू नहीं करता है और एप्लिकेशन तो दुर्घटना होगा (भले ही प्रोटोकॉल विधि की आवश्यकता है) कर रहे हैं का जवाब है।
ठीक है, यह वास्तव में प्रश्न का उत्तर नहीं है, लेकिन आप देख रहे हैं कि कैसे अपने खुद के प्रतिनिधि बनाने के लिए शायद कुछ बहुत आसान आपके लिए एक बेहतर जवाब हो सकता है।
क्योंकि मैं शायद ही कभी जरूरत मैं शायद ही मेरी प्रतिनिधियों को लागू। मैं एक प्रतिनिधि वस्तु के लिए केवल एक ही प्रतिनिधि हो सकता है। तो अगर आप एक तरह से संचार के लिए अपने प्रतिनिधि / डेटा गुजर से आप ज्यादा सूचनाओं के साथ की बेहतर हैं चाहता हूँ।
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];
}
यहाँ प्रतिनिधियों को बनाने के लिए एक सरल तरीका है
ज फ़ाइल में प्रोटोकॉल बनाएँ। सुनिश्चित करें कि प्रोटोकॉल UIViewController के नाम के बाद @class उपयोग करने से पहले परिभाषित किया गया है< As the protocol I am going to use is UIViewController class>.
कदम: 1: एक नया वर्ग प्रोटोकॉल "YourViewController" नाम जो UIViewController वर्ग के उपवर्ग हो सकता है और दूसरा ViewController के लिए इस वर्ग आवंटित करेगा बनाएँ।
कदम: 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];
}
}
अपने खुद के प्रतिनिधि बनाने के लिए पहले आप को लागू करने के बिना एक प्रोटोकॉल बना सकते हैं और आवश्यक तरीकों घोषित करने के लिए, की जरूरत है। और फिर अपने हैडर वर्ग में इस प्रोटोकॉल को लागू जहां प्रतिनिधि या प्रतिनिधि के तरीकों को लागू करना चाहते हैं।
एक प्रोटोकॉल नीचे के रूप में घोषित किया जाना चाहिए:
@protocol ServiceResponceDelegate <NSObject>
- (void) serviceDidFailWithRequestType:(NSString*)error;
- (void) serviceDidFinishedSucessfully:(NSString*)success;
@end
यह सेवा वर्ग जहां कुछ काम किया जाना चाहिए है। यह कैसे प्रतिनिधि और कैसे प्रतिनिधि सेट करने के लिए परिभाषित करने के लिए पता चलता है। कार्यान्वयन कक्षा में काम के बाद पूरा हो गया है प्रतिनिधि के तरीकों कहा जाता है।
@interface ServiceClass : NSObject
{
id <ServiceResponceDelegate> _delegate;
}
- (void) setDelegate:(id)delegate;
- (void) someTask;
@end
@implementation ServiceClass
- (void) setDelegate:(id)delegate
{
_delegate = delegate;
}
- (void) someTask
{
/*
perform task
*/
if (!success)
{
[_delegate serviceDidFailWithRequestType:@”task failed”];
}
else
{
[_delegate serviceDidFinishedSucessfully:@”task success”];
}
}
@end
यह जहां सेवा वर्ग खुद के लिए प्रतिनिधि की स्थापना द्वारा कहा जाता है से मुख्य दृश्य वर्ग है। और यह भी प्रोटोकॉल हैडर कक्षा में कार्यान्वित किया जाता है।
@interface viewController: UIViewController <ServiceResponceDelegate>
{
ServiceClass* _service;
}
- (void) go;
@end
@implementation viewController
//
//some methods
//
- (void) go
{
_service = [[ServiceClass alloc] init];
[_service setDelegate:self];
[_service someTask];
}
यही है, और इस वर्ग में प्रतिनिधि तरीकों को लागू करने से, नियंत्रण वापस एक बार आपरेशन / कार्य किया जाता है आ जाएगा।
अस्वीकरण: यह है Swiftकि कैसे एक बनाने के लिए के संस्करण delegate।
तो, प्रतिनिधियों क्या हैं? ... सॉफ्टवेयर के विकास में, सामान्य पुन: प्रयोज्य समाधान आर्किटेक्चर कि किसी दिए गए संदर्भ में अधिक होने वाली समस्याओं को हल करने में मदद कर रहे हैं, इन "टेम्पलेट्स", तो बात करने के लिए, सबसे अच्छा डिजाइन पैटर्न के रूप में जाना जाता है। प्रतिनिधि एक डिजाइन पैटर्न है कि एक वस्तु किसी अन्य वस्तु को संदेश भेजने के लिए जब एक विशिष्ट घटना होता है की अनुमति देता है कर रहे हैं। एक वस्तु एक कॉल कोई कार्रवाई करने के लिए एक वस्तु बी कल्पना कीजिए। एक बार कार्रवाई पूर्ण होने पर, वस्तु एक पता होना चाहिए बी काम पूरा कर लिया है कि और आवश्यक कार्रवाई करें, इस प्रतिनिधियों की मदद से प्राप्त किया जा सकता!
एक बेहतर विवरण के लिए, मैं एक साधारण आवेदन में स्विफ्ट के साथ, कि वर्गों के बीच डेटा गुजरता एक कस्टम प्रतिनिधि बनाने का तरीका, आप दिखाने जा रहा हूँ को डाउनलोड करने या इस स्टार्टर परियोजना क्लोनिंग और इसे चलाने से शुरू!
आप दो वर्गों के साथ एप्लिकेशन देख सकते हैं, ViewController Aऔर ViewController B। बी दो बार देखा गया है कि नल पर की पृष्ठभूमि का रंग बदल जाता है ViewController, कुछ भी नहीं जटिल है ना? अच्छी तरह से अब के लिए एक आसान तरीका है जब क्लास B पर देखा गया उपयोग किया जाता है भी वर्ग एक की पृष्ठभूमि का रंग बदलने के लिए सोचते हैं।
समस्या यह है कि इस बार देखा गया वर्ग बी का हिस्सा हैं और वर्ग एक के बारे में पता नहीं है, इसलिए हम इस दो वर्गों के बीच संवाद करने के लिए एक रास्ता खोजने की जरूरत है, और कहा कि जहां प्रतिनिधिमंडल चमकता है। ताकि आप जब आपको उसकी आवश्यकता की नकल पुस्तिकाओं के रूप में इसका उपयोग कर सकते हैं मैं 6 चरणों में कार्यान्वयन विभाजित।
चरण 1: ClassBVC फ़ाइल में pragma निशान चरण 1 के लिए देखो और इस ऐड
//MARK: step 1 Add Protocol here.
protocol ClassBVCDelegate: class {
func changeBackgroundColor(_ color: UIColor?)
}
पहला कदम एक बनाने के लिए है protocolइस मामले में, हम, वर्ग बी में प्रोटोकॉल का निर्माण करेगा प्रोटोकॉल के अंदर आप के रूप में कई कार्यों है कि आप अपने कार्यान्वयन की आवश्यकताओं के आधार पर करना चाहते हैं बना सकते हैं। इस मामले में, हम सिर्फ एक साधारण समारोह है कि एक वैकल्पिक स्वीकार करता है UIColorएक तर्क के रूप। शब्द जोड़कर अपने प्रोटोकॉल नाम के लिए एक अच्छा अभ्यास है delegateइस मामले में वर्ग के नाम के अंत में,, ClassBVCDelegate।
चरण 2: में pragma निशान चरण 2 के लिए देखो ClassVBCऔर इस ऐड
//MARK: step 2 Create a delegate property here.
weak var delegate: ClassBVCDelegate?
यहाँ हम सिर्फ वर्ग के लिए एक प्रतिनिधि संपत्ति बनाने के लिए, इस संपत्ति को अपनाने चाहिए protocolप्रकार है, और यह वैकल्पिक किया जाना चाहिए। इसके अलावा, आप, चक्र और संभावित मेमोरी लीक बनाए रखने के लिए यदि आप नहीं पता है कि इसका मतलब है अब के लिए चिंता मत करो क्या से बचने के लिए संपत्ति से पहले कमजोर कीवर्ड जोड़ना चाहिए, सिर्फ इस कीवर्ड जोड़ने के लिए याद है।
चरण 3: handleTap अंदर pragma निशान चरण 3 के लिए देखो methodमें ClassBVCऔर इस ऐड
//MARK: step 3 Add the delegate method call here.
delegate?.changeBackgroundColor(tapGesture.view?.backgroundColor)
एक बात है कि आप जानते हैं, अनुप्रयोग चलाने के लिए और किसी भी दृश्य पर नल चाहिए, तो आप किसी भी नए व्यवहार नहीं देखेंगे और यह सही है, लेकिन बात यह है कि मैं कहना चाहता हूँ कि एप्लिकेशन जब प्रतिनिधि कहा जाता है यह दुर्घटनाग्रस्त नहीं कर रहा है, और यह इसलिए है क्योंकि हम यह एक वैकल्पिक मूल्य के रूप में बना सकते हैं और यही कारण है कि यह और भी सौंप क्रैश नहीं करेंगे अभी मौजूद नहीं है है। चलो अब के लिए जाने के ClassAVCलिए फ़ाइल और इसे बनाने के लिए, प्रत्यायोजित।
चरण 4: में handleTap विधि के अंदर pragma निशान चरण 4 के लिए देखो ClassAVCऔर यह इस तरह अपनी कक्षा प्रकार के बगल में जोड़ें।
//MARK: step 4 conform the protocol here.
class ClassAVC: UIViewController, ClassBVCDelegate {
}
अब ClassAVC अपनाया ClassBVCDelegateप्रोटोकॉल, जैसा कि आप देख सकते हैं कि आपके संकलक आप एक त्रुटि है कि कहते हैं, "प्रकार ClassBVCDelegate '' ClassAVC प्रोटोकॉल के अनुरूप नहीं है 'दे रहा है और यह केवल इसका मतलब है कि आप अभी तक प्रोटोकॉल के तरीकों का उपयोग नहीं किया, कल्पना करें कि जब कक्षा एक प्रोटोकॉल को गोद ले वर्ग बी के साथ एक अनुबंध पर हस्ताक्षर करने की तरह है और इस अनुबंध कहते हैं, "किसी भी वर्ग मुझे मेरे कार्यों का उपयोग करना चाहिए अपनाने!"
त्वरित टिप्पणी: यदि आप एक से आते हैं, तो Objective-Cपृष्ठभूमि आप शायद सोच रहे हैं कि आप भी उस विधि वैकल्पिक बनाने कि त्रुटि चुप रहो सकते हैं, लेकिन मेरे आश्चर्य के लिए, और शायद तुम्हारा, Swiftभाषा वैकल्पिक समर्थन नहीं करता है protocols, अगर आप यह करने के लिए आप बना सकते हैं चाहते हैं आपके लिए एक एक्सटेंशन protocolया अपने में @objc कीवर्ड का उपयोग protocolकार्यान्वयन।
व्यक्तिगत रूप से, अगर मैं अलग वैकल्पिक तरीकों मैं अलग में तोड़ने के लिए पसंद करेंगे के साथ एक प्रोटोकॉल बनाने के लिए protocols, कि जिस तरह से मैं अपने वस्तुओं के लिए एक ही जिम्मेदारी दे रही है की अवधारणा का पालन करेंगे, लेकिन यह विशिष्ट कार्यान्वयन के आधार पर भिन्न हो सकते हैं।
यहाँ है वैकल्पिक तरीकों के बारे में एक अच्छा लेख।
चरण 5: के अंदर segue विधि के लिए तैयार करने और इस ऐड pragma निशान चरण 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: अंत में, में pragma चरण 6 के लिए देखो ClassAVCऔर के के कार्यों का उपयोग करते हैं protocol, समारोह टाइप करना आरंभ changeBackgroundColor और आप देखेंगे कि यह ऑटो को पूरा करने के लिए है कि आप इसे देखेंगे। आप किसी भी कार्यान्वयन में जोड़ सकते हैं अंदर यह, इस उदाहरण में, हम बस पृष्ठभूमि रंग बदल जाएगा, इस जोड़ें।
//MARK: step 6 finally use the method of the contract
func changeBackgroundColor(_ color: UIColor?) {
view.backgroundColor = color
}
अब एप्लिकेशन को चलाने के!
Delegatesहर जगह हैं और आप शायद, यहां तक कि नोटिस के बिना उन्हें इस्तेमाल करता है, तो आप एक बनाने के tableviewअतीत आप प्रतिनिधिमंडल के कई वर्गों के लिए प्रयोग किया जाता में UIKITउनके आसपास काम करता है और कई अन्य frameworksभी, वे इन मुख्य समस्याओं को हल।
बधाई हो, तुम सिर्फ एक कस्टम प्रतिनिधि को लागू, मुझे पता है कि आप शायद सोच रहे हैं तो बस इस के लिए, इतना मुसीबत? अच्छी तरह से, प्रतिनिधिमंडल को समझने के लिए अगर आप एक बनना चाहते हैं एक बहुत ही महत्वपूर्ण डिजाइन पैटर्न है iOSडेवलपर, और हमेशा ध्यान में रखना है कि वे वस्तुओं के बीच आमने-सामने की रिश्ता है कि।
आप मूल ट्यूटोरियल देख सकते हैं यहां
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{
}
उत्तर वास्तव में उत्तर दिया जाता है, लेकिन मैं आप एक प्रतिनिधि बनाने के लिए एक "की नकल पुस्तिकाओं" देने के लिए करना चाहते हैं:
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
एक उदाहरण के साथ शुरू करते हैं, अगर हम एक उत्पाद ऑनलाइन खरीद सकते हैं, यह अलग teams.So द्वारा नियंत्रित शिपिंग / वितरण की तरह प्रक्रिया के माध्यम से शिपिंग पूरा हो जाता है, तो चला जाता है, शिपिंग टीम वितरण टीम को सूचित करना चाहिए और यह प्रसारण के रूप में एक संचार इस जानकारी के लिए एक होना चाहिए भूमि के ऊपर हो के लिए अन्य लोगों / विक्रेता केवल आवश्यक लोगों को यह जानकारी पहुंचाना चाहेंगे होगा।
अगर हम हमारे अनुप्रयोग के संदर्भ में लगता है तो, एक घटना एक ऑनलाइन आदेश हो सकता है और अलग-अलग टीमों के कई दृश्य हैं की तरह हो सकता है।
यहाँ कोड शिपिंग टीम और DeliveryView वितरण टीम के रूप में के रूप में ShippingView विचार है:
//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;
कि in.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];
}
}
}];
}
यहाँ सब कस्टम प्रतिनिधि class.after है कि आप इस प्रतिनिधि पद्धति जहां आप उदाहरण want.for उपयोग कर सकते हैं के लिए सेट कर रहे हैं ...
उस के बाद मेरी एक और ViewController आयात में
इस तरह प्रतिनिधि विधि फोन करने के लिए कार्रवाई बनाने
- (IBAction)dropDownBtn1Action:(id)sender {
DropDownViewController *vehicleModelDropView = [[DropDownViewController alloc]init];
vehicleModelDropView.dropDownType = DDCITY;
vehicleModelDropView.delegate = self;
[self presentViewController:vehicleModelDropView animated:YES completion:nil];
}
इस तरह है कि कॉल प्रतिनिधि विधि के बाद
- (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;
}
}
//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: (NSInteger) टैग {NSLog @ ( "टैग% d", टैग);
}
प्रतिनिधि: - बनाएँ
@protocol addToCartDelegate <NSObject>
-(void)addToCartAction:(ItemsModel *)itemsModel isAdded:(BOOL)added;
@end
भेजें और आप डेटा भेज रहे हैं देखने के लिए किसी प्रकार कृपया
[self.delegate addToCartAction:itemsModel isAdded:YES];