2009-08-28 17 views
35

में तर्क क्या कोई तरीका है कि मैं चयनकर्ता में तर्क पारित कर सकता हूं?@ चयनकर्ता

उदाहरण: मैं इस विधि

- (void)myMethod:(NSString*)value1 setValue2:(NSString*)value2{ 

} 

है और मैं एक चयनकर्ता दो तर्क गुजर के माध्यम से इस समारोह फोन की जरूरत है।

[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(/*my method*/) userInfo:nil repeats:YES]; 

मैं यह कैसे कर सकता हूं?

उत्तर

56

आप एक NSInvocation वस्तु के बाद से

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds 
           invocation:(NSInvocation *)invocation 
            repeats:(BOOL)repeats; 

इसके बजाय, आप तर्क पारित करने के लिए अनुमति देगा;: NSTimer विधि इस्तेमाल कर सकते हैं वह यह है कि

एक ऑब्जेक्टिव-सी संदेश स्थिर प्रदान की गई,, यह एक कार्रवाई एक वस्तु में बदल गया है: एक NSInvocation वस्तु है, जैसा कि docs यह परिभाषित करते हैं।

- (void)timerFireMethod:(NSTimer*)theTimer 

एक NSInvocation आप लक्ष्य, चयनकर्ता, और तर्क है कि आप में से गुजरती हैं स्थापित करने के लिए अनुमति देता है::

एक चयनकर्ता का उपयोग करके एक NSTimer वस्तु बनाने जबकि विधि जा रहा है की प्रारूप की आवश्यकता है

SEL selector = @selector(myMethod:setValue2:); 

NSMethodSignature *signature = [MyObject instanceMethodSignatureForSelector:selector]; 
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; 
[invocation setSelector:selector]; 

NSString *str1 = @"someString"; 
NSString *str2 = @"someOtherString"; 

//The invocation object must retain its arguments 
[str1 retain]; 
[str2 retain]; 

//Set the arguments 
[invocation setTarget:targetInstance]; 
[invocation setArgument:&str1 atIndex:2]; 
[invocation setArgument:&str2 atIndex:3]; 

[NSTimer scheduledTimerWithTimeInterval:0.1 invocation:invocation repeats:YES]; 

कहाँ MyObject वर्ग कि myMethod:setValue2: घोषित कर दिया और पर कार्यान्वित किया जाता है है - instanceMethodSignatureForSelector: एक सुविधा कामकाज है NSObject पर घोषित किया गया है जो आपके लिए NSMethodSignature ऑब्जेक्ट देता है, जिसे NSInvocation पर पास किया जा सकता है।

ही, ध्यान दें करने के लिए, setArgument:atIndex: साथ, सूचकांक तर्क विधि सूचकांक 2. पर चयनकर्ता शुरुआत के रूप में स्थापित किए गए दस्तावेज़ों से पारित होने के लिए के लिए:

सूचकांकों 0 और 1 छिपा तर्क स्वयं से संकेत मिलता है और क्रमशः _cmd; आपको इन मानों को सीधे सेट लक्ष्य के साथ सेट करना चाहिए: और सेट चयनकर्ता: विधियां।आम तौर पर किसी संदेश में पारित तर्कों के लिए सूचकांक 2 और अधिक का उपयोग करें।

+1

यह मेरा से बेहतर जवाब है। आपको अनावश्यक तरीकों से अपने कार्यान्वयन को प्रदूषित करने से बचने के लिए ऐसा करना चाहिए। –

+3

ध्यान दें कि, 'str1' और 'str2' स्थिर रूप से आवंटित नहीं थे, आप उन्हें लीक करेंगे। 'एनएसटीमर 'को अपने आमंत्रण ऑब्जेक्ट में' -retainArguments' भेजने के रूप में दस्तावेज किया गया है, लेकिन यह आपके लिए आमंत्रण ऑब्जेक्ट को' -retainArguments' भेजने के लिए चोट नहीं पहुंचाएगा। समस्या स्वयं तर्कों को बरकरार रख रही है, फिर भी उन्हें बनाए रखने के लिए आमंत्रण बता रही है। अपने आप को आमंत्रण तर्कों को न रखें! आवेदक इसे संभाल लें - और, यहां, टाइमर इसे स्वयं संभाल दें। –

+3

विधि हस्ताक्षर पुनर्प्राप्त करने में किए गए अनुसार 'targetInstance' की कक्षा को हार्डकोड न करें। यदि आप वास्तव में '+ instanceMethodSignatureForSelector:' का उपयोग करना चाहते हैं, तो आप '[[targetInstance class] instanceMethodSignatureForSelector: selector] 'का उपयोग कर सकते हैं, लेकिन यह अनावश्यक रूप से जटिल है - बस' [targetInstance methodSignatureForSelector: selector] 'का उपयोग करके विधि हस्ताक्षर के लिए ऑब्जेक्ट से पूछें। । –

-2
@selector(myMethod:setValue2:) 

के बाद से अपने विधि के लिए चयनकर्ता सिर्फ myMethod लेकिन इसके बजाय myMethod:setValue2: नहीं कहा जाता है।

इसके अलावा (और मैं यहां आधार से बाहर हो सकता हूं), मुझे विश्वास है कि तकनीकी रूप से आप कोलों के बीच शब्दों को छोड़ सकते हैं और इस प्रकार @selector(myMethod::) का भी उपयोग कर सकते हैं, लेकिन जब तक अन्य इसकी पुष्टि नहीं कर लेते तब तक मुझे इस पर उद्धरण न दें।

+2

यह गलत है। चयनकर्ता कॉलन के बीच सबकुछ सहित विधि का पूरा नाम है। 'myMethod ::' और 'myMethod: setValue2:' अलग चयनकर्ता हैं, जो अलग-अलग कार्यान्वयन से जुड़े होंगे जबतक कि आपने कुछ रनटाइम जादू नहीं किया है। –

+0

ठीक है। मैं आधार से दूर था। – jbrennan

27

scheduledTimerWithTimeInterval: के लिए, आपके द्वारा चुने गए चयनकर्ता के पास केवल एक तर्क हो सकता है। इसके अलावा, इसका एक तर्क NSTimer * ऑब्जेक्ट होना चाहिए। दूसरे शब्दों में, चयनकर्ता निम्नलिखित रूप ले लेना चाहिए:

- (void)timerFireMethod:(NSTimer*)theTimer 

क्या तुम कर सकते हो userInfo शब्दकोश में तर्क की दुकान और चयनकर्ता आप टाइमर कॉलबैक से चाहते हैं कहते हैं:

- (void)startMyTimer { 
    /* ... Some stuff ... */ 
    [NSTimer scheduledTimerWithTimeInterval:0.1 
            target:self 
            selector:@selector(callMyMethod:) 
            userInfo:[NSDictionary dictionaryWithObjectsAndKeys:someValue, 
         @"value1", someOtherValue, @"value2", nil] 
            repeats:YES]; 
} 

- (void)callMyMethod:(NSTimer *)theTimer { 
    NSString *value1 = [[theTimer userInfo] objectForKey:@"value1"]; 
    NSString *value2 = [[theTimer userInfo] objectForKey:@"value2"]; 
    [self myMethod:value1 setValue2:value2]; 
} 
+2

यह isiaatz से ऊपर पोस्ट की गई विशिष्ट विधि के लिए सही है। अगर वह सिर्फ एक उदाहरण था और आप सामान्य रूप से जानना चाहते हैं कि चयनकर्ता को कई तर्क कैसे भेजें, तो कृपया अपना प्रश्न – h4xxr

+0

संशोधित करें क्योंकि यह स्वीकार्य उत्तर से बेहतर है क्योंकि यह अधिक संक्षिप्त है। –

+1

मैं इसे बेहतर भी पसंद करता हूं –

2

ब्लॉक के लिए एक नौकरी की तरह लग रहा है (यह मानते हुए हिमपात तेंदुए के लिए लक्षित है।)

-jcr

0

ब्लॉक एक स्पष्ट जवाब की तरह अब लग रहे हैं ... लेकिन वहाँ एक और मुहावरा है कि बहुत था आम क्लासिक क्रम में, एक वस्तु में अपने तर्क अचार:

- (void)doMyMethod:(NSDictionary *)userInfo 
{ 
    [self myMethod: [userInfo objectForKey:@"value1"] setValue2: [userInfo objectForKey:@"value2"]]; 
} 
- (void)myMethod:(NSString*)value1 setValue2:(NSString*)value2{ 

} 

अब आप

करने के लिए प्रेषण कर सकते हैं
संबंधित मुद्दे