उद्देश्य-सी में कक्षा विधियों के एनएसएआरएआरए (या एनएसएमयूटेबलएरे) का निर्माण कैसे करें?


14

मैं Objective-C में विधियों का एनएसएआरएआर बनाने की कोशिश कर रहा हूं।

मैं बंदरगाह के लिए ऑब्जेक्टिव-सी को यह किया है और मैं नहीं जानता कि कैसे की एक सरणी का निर्माण करने के लिए (सी में निम्नलिखित की तरह कुछ क्या मैं यहाँ पूरा करने के लिए कोशिश कर रहा हूँ है) फ़ंक्शन पॉइंटर्स (ऑब्जेक्टिव-सी वर्ल्ड, क्लास विधियों में) संकलन-समय पर।

उद्देश्य-सी में मेरे पास निम्नलिखित हैं।

- (void)handleCommandA { ... } 
- (void)handleCommandB { ... } 

/* Now how to add above 2 functions into NSArray? */ 
NSArray *handler_table = [NSArray arrayWithObjects:... ]; /* This doesn't seem to work. */ 
5

उपयोग NSValue।

उदाहरण के लिए:

NSArray* handlers = [NSArray arrayWithObjects:[NSValue valueWithPointer:handleA] ... ]; 

तो उपयोग करने के लिए:

handleptr* handle = (handlerptr*)[[handlers objectAtIndex:0] pointerValue]; 
handle(foo_bar); 

28

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

इस प्रकार आपके पास तीन विकल्प हैं;

  1. एक नियमित रूप से सी-टाइप सरणी
  2. का प्रयोग करें एक NSObject व्युत्पन्न वर्ग है कि उन्हें फोन करेगा में कार्यों गुना।
  3. प्रोटोकॉल का उपयोग करें।

दूसरी संभावना अच्छे है और इस के लिए आप चयनकर्ता परिणाम धारण करने के लिए NSValue वर्ग का उपयोग कर सकते हैं। उदा;

NSValue* selCommandA = [NSValue valueWithPointer:@selector(handleCommandA:)]; 
NSValue* selCommandB = [NSValue valueWithPointer:@selector(handleCommandB:)]; 

NSArray *handler_table = [NSArray arrayWithObjects:selCommandA, selCommandB, nil ]; 

जब आपने सरणी से सही प्रविष्टि पुनर्प्राप्त की है, तो वापस कनवर्ट करने के लिए;

SEL mySelector = [selCommand pointerValue]; 
[someObject performSelector:mySelector]; 

(नोट मुझे लगता है कि अपने उद्देश्य-सी वाक्य रचना है कि इन वैश्विक कार्यों एक वस्तु पर तरीकों और नहीं के रूप में इस्तेमाल किया जा करने का इरादा कर रहे हैं से संभालने कर रहा हूँ। आप तो आप उन्हें लिखना चाहिए उन्हें विश्व स्तर पर उपयोग करना चाहते हैं आप सादे सी में होंगे।

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

उदा।

// some header 
@protocol CommandHandler 
@required 
-(void) handleCommandA; 
-(void) handleCommandB; 
@end 

// some other header 
@interface someClass : NSObject<CommandHandler> 
{ 
// you will receive compiler warnings if you do not implement the protocol functions 
} 

आपका हैंडलिंग और प्रेषण कोड तब "कमांडहैंडलर" प्रकार की वस्तुओं के साथ काम करने के लिए लिखा जाता है। E.g

-(void) registerForCommands:(CommandHandler*)handler 
  0

मैं के रूप में यह बहुत आसान डिबगिंग देते थे और संकेत के बजाय तार का उपयोग करना पसंद करते हैं। NSStringFromSelector() और NSSelectorFromString() पर देखें। 17 may. 092009-05-17 09:10:39

+1

चयनकर्ता का उपयोग करके छोटे सुधार वास्तव में ऐसा लगता है: [someObject performSelector: mySelector]; 19 jan. 112011-01-19 03:30:33


4

उद्देश्य-सी में, आप विधियों के चारों ओर पास नहीं करते हैं; आप चयनकर्ता पास करते हैं, जो मूल रूप से विधियों के कैननिकल नाम हैं। फिर, ऑब्जेक्ट को किसी चयनकर्ता संदेश का जवाब देने के लिए, आप इसे performSelector: भेजते हैं। उदाहरण के लिए:

NSString *exampleString = [NSString stringWithString:@"Hello"]; 
SEL methodName = @selector(stringByAppendingString:); 
    // ^This is the selector. Note that it just represents the name of a 
    // message, and doesn't specify any class or implementation 
NSString *combinedString = [exampleString performSelector:methodName withObject:@" world!"]; 

आप क्या चाहते हैं चयनकर्ताओं आप में रुचि रखते हैं के नामों वाले NSStrings की एक सरणी बनाने के लिए है ऐसा करने के लिए समारोह NSStringFromSelector() उपयोग कर सकते हैं।। फिर, जब आप उनका उपयोग करना चाहते हैं, तो मूल चयनकर्ता को वापस पाने के लिए NSSelectorFromString() पर कॉल करें और उचित ऑब्जेक्ट के performSelector: पर पास करें।(जैसा कि ऊपर के उदाहरण में दिखाया गया है, रिसीवर एक चयनकर्ता में एन्कोड किया गया है नहीं - बस विधि नाम - तो आप के रूप में अच्छी रिसीवर स्टोर करने के लिए आवश्यकता हो सकती है।)