2012-03-25 26 views
6

में मैंने एक UITextField को उपclassed है और मैं एक वर्ण टाइप होने पर अधिसूचित होने के लिए उप-वर्ग के अंदर textField:shouldChangeCharactersInRange:replacementString: जैसी विधि का उपयोग करना चाहता हूं और यदि आवश्यक हो तो परिवर्तन को अवरुद्ध करें, लेकिन सेटिंग से बचें खेतों में खुद को प्रतिनिधि।टेक्स्टफ़िल्ल्ड: चाहिएChangeCharactersInRange: replacementString: subclass

अगर मैं ओवरराइड keyboardInput:shouldInsertText:isMarkedText: और keyboardInputShouldDelete: मैं वांछित प्रभाव प्राप्त कर सकते हैं मैंने पाया, दुर्भाग्य से इन तरीकों निजी हैं और वर्ग का उपयोग कर कुछ भी App स्टोर सबमिट करने की प्रक्रिया के माध्यम से यह नहीं होगा।

कोई भी सार्वजनिक विधि के बारे में जानता है जो एक ही चीज़ प्राप्त करता है और क्षेत्र को अपने प्रतिनिधि होने की आवश्यकता नहीं होती है?

अद्यतन:

मैं एक अलग वस्तु बनाने के सुझाव के साथ चला गया बस प्रतिनिधि है, जो खुद को संदेश अग्रेषित करने एक प्रतिनिधि हो सकता है किया जाना है।

+0

आप स्पष्ट कर सकते हैं? यह तुरंत स्पष्ट नहीं है कि आप टेक्स्टफिल्ड का उपयोग क्यों नहीं करेंगे: चाहिएChangeCharactersInRange:, यानी subclass को अपने उदाहरणों को अपने स्वयं के प्रतिनिधियों के रूप में सेट करने के लिए मिलता है। – Obliquely

+1

इसे अपने स्वयं के प्रतिनिधि के रूप में स्थापित करने में एकमात्र समस्या एक वास्तविक प्रतिनिधि को घटनाओं को अग्रेषित कर रही है जो यूआईटीएक्स्टफिल्ड घटनाओं का जवाब दे सकती है। वर्तमान में, मैं addTarget का उपयोग कर रहा हूं: क्रिया: forControlEvent: आंतरिक रूप से उन घटनाओं का जवाब देने के लिए। –

उत्तर

2

पहले UITextField को उपclass करने का प्रयास करने के बाद, मैंने इसके बाद से बचने के लिए सीखा है और इसके बजाय प्रतिनिधि मार्ग पर जाना है (इसमें - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string नामक एक समान विधि है जो मुझे लगता है कि मैंने जो वर्णन किया है उसे करना चाहिए)।

+0

निश्चित रूप से, लेकिन यह केवल तभी उपलब्ध है जब मैंने टेक्स्टफील्ड को अपना प्रतिनिधि बनने के लिए सेट किया है, जिसे मैं टालना चाहता हूं। –

+1

मैं यूआईटीएक्स्टफिल्ड को अपना स्वयं का प्रतिनिधि बनाना पसंद नहीं करता - मैं आम तौर पर प्रतिनिधि के वर्ग के रूप में अपने 'स्कॉटटेक्स्टफिल्ल्ड वैलिडेटर' सबक्लास का उपयोग करता हूं (जिसमें सभी विधियों/राज्यों की आवश्यकता होती है)। UITextField को स्वयं का प्रतिनिधि बनने का कोई कारण नहीं है। –

+0

हाँ मैं इस दृष्टिकोण की तरफ झुका रहा हूं। प्रतिनिधिमंडल के गुणों को मजबूत करने के लिए –

0

आप uitextfield के प्रतिनिधि विधि का उपयोग कर सकते हैं,

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 
{ 

} 

और भूल नहीं है viewDidLoad में अपने textfield.delegate = self स्थापित करने के लिए।

2

यहां देखने का एक तरीका सेट डिलीगेट: विधि को ओवरराइड करना है और फिर कुछ संदेश अग्रेषण करना है। आप यह सुनिश्चित करने के लिए [super setDelegate: self] का उपयोग कर सकते हैं कि आपकी कॉल प्रतिनिधि संदेशों पर पहली बार आती है। सेटडिलेगेट के अपने ओवरराइड में: एक आंतरिक इवर सेट करें, उदा।

- (void) setDelegate: (id<UITextFieldDelegate>) internalDelegate; 
{ 
    [setInternalDelegate: internalDelegate]; 
} 

फिर यूआईटीएक्स्टफाल्ड प्रतिनिधि पद्धतियों में से प्रत्येक के लिए प्रतिनिधि संदेश पर अग्रेषित करने से पहले अपनी बात करें, उदा।

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string; 
{ 
     // do your thing with range and replacement string 

     // now forward message on the 'other' delegate  
     [[self internalDelegate] textField: self shouldChangeCharactersInRange: range replacementString: string]; 
} 

आमतौर पर, आप प्रतिनिधि तरीकों के सभी ओवरराइड करने के लिए, भले ही उनमें तुम सब के अधिकांश के लिए एक सीधे आगे है चाहता हूँ।

अद्यतन आप टिप्पणियों में ध्यान देते हैं कि अग्रेषण दृष्टिकोण मुद्दों को उठा रहा है। यदि ऐसा है, तो पारंपरिक प्रतिनिधिमंडल जाने का रास्ता है। (और, आम तौर पर, यह जाने का तरीका है - हालांकि मैंने एक या दो बार प्रतिनिधि को अग्रेषित करने का उपयोग किया है, मुझे यकीन नहीं है कि, हिंडसाइट के साथ, यह बिल्कुल जरूरी था और मैंने यह देखने के लिए जांच नहीं की है कि क्या मैं 'UITextField के साथ यह किया है। @Scott Corscadden है और यह सिफारिश नहीं करता।)

सबसे आम पैटर्न ViewController उस दृश्य जिसमें UITextField एक subview प्रतिनिधि है के बाद लग रहा है बनाने के लिए है। यदि आपके पास उपclass के साथ काम करने की आवश्यकता है तो आप अपने उत्तर में नहीं कहते हैं। यदि आप UITextField में दिलचस्प सामग्री पैक कर रहे हैं तो यह हो सकता है कि, आप हमेशा एक और पोस्टर सुझा सकते हैं और UITextField के लिए एक साथी वर्ग बना सकते हैं जो उस काम को करता है और प्रतिनिधि के रूप में उपयोग करता है। किसी भी मामले में, यदि आवश्यकता हो, तो आप अपने UITextField सबक्लास पर अतिरिक्त विधियों को कॉल करने के लिए हमेशा प्रतिनिधि ऑब्जेक्ट प्राप्त कर सकते हैं, उदा।

// in the delegate object class 

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string; 
{ 
     [delegate doSomeExtraThingInTheTextFieldSubclassThatItSeemsToMakeSenseToDoThereRatherThanHere]; 

     // maybe that's it, or maybe this object also wants to do something here... 
} 
+0

क्या कोई तरीका है कि मैं उन्हें लागू किए बिना अग्रेषित कर सकता हूं? तो केवल मेरे सबक्लास उपकरण को जिस तरीके से बुलाया जाता है, लेकिन बाकी सब कुछ अगले प्रतिनिधि के पास पास किया जाता है? –

+1

मुझे ऐसा नहीं लगता है। लेकिन UITextFieldDelegate प्रोटोकॉल में 7 संदेशों के लिए अग्रेषण को लागू करने में केवल पांच मिनट लगते हैं। यह देखते हुए कि संदेश भेजने की तुलना में यह यूआई और लोग धीमे हैं, ओवरहेड अप्रासंगिक है। – Obliquely

+1

कोड पर कटौती करना अच्छा होगा, हालांकि;) –

1

आप इसे प्राप्त करने के लिए उद्देश्य-सी रनटाइम के साथ खेल सकते हैं।निम्नलिखित कोड मेरे लिए काम कर रहा है। विचार है:

    उपवर्ग में
  • हम स्वयं को delegate गुण सेट;
  • हम setDelegate: विधि को ओवरराइड करते हैं जिसमें हम एक वेरिएबल (forwardDelegate) पर आपूर्ति प्रतिनिधि को स्टोर करते हैं;
  • respondsToSelector:, forwardInvocation: और methodSignatureForSelector: ओवरराइड करके हम या तो स्वयं को विधि कॉल करते हैं या इसे forwardDelegate सहेजने के लिए अग्रेषित करते हैं।

// MyTextField.h 
@interface MyTextField : UITextField 
@end 

// MyTextField.m 
@interface MyTextField() <UITextFieldDelegate> 
@end 

@implementation MyTextField { 
    id forwardDelegate; 
} 

- (void) myTextFieldCommonInit 
{ 
    [super setDelegate:self]; 
} 

- (id) initWithCoder:(NSCoder *)coder 
{ 
    if ((self = [super initWithCoder:coder])) { 
     [self myTextFieldCommonInit]; 
    } 
    return self; 
} 

- (id) initWithFrame:(CGRect)frame 
{ 
    if ((self = [super initWithFrame:frame])) { 
     [self myTextFieldCommonInit]; 
    } 

    return self; 
} 

- (void) setDelegate:(id)delegate 
{ 
    forwardDelegate = delegate; 
} 

- (BOOL) respondsToSelector:(SEL)selector 
{ 
    if ([super respondsToSelector:selector]) { 
     return YES; 
    } else { 
     return [forwardDelegate respondsToSelector:selector]; 
    } 
} 

- (void) forwardInvocation:(NSInvocation *)invocation 
{ 
    if ([super respondsToSelector:[invocation selector]]) { 
     [super forwardInvocation:invocation]; 
    } else if ([forwardDelegate respondsToSelector:[invocation selector]]) { 
     [invocation invokeWithTarget:forwardDelegate]; 
    } else { 
     [self doesNotRecognizeSelector:[invocation selector]]; 
    } 
} 

- (NSMethodSignature *) methodSignatureForSelector:(SEL)selector 
{ 
    NSMethodSignature *signature = [super methodSignatureForSelector:selector]; 
    if (signature) { 
     return signature; 
    } else { 
     return [forwardDelegate methodSignatureForSelector:selector]; 
    } 
} 

#pragma mark - UITextFieldDelegate 

- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 
{ 
    ... 
} 

@end