2009-07-30 9 views
15

ऐप्पल वास्तव में मजाकिया है। मेरा मतलब है, वे कहते हैं कि यह काम करता है:उत्तरदाता श्रृंखला में अगले उत्तरदाता को किसी ईवेंट को पास करने की चाल क्या है?

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch* touch = [touches anyObject]; 
    NSUInteger numTaps = [touch tapCount]; 
    if (numTaps < 2) { 
     [self.nextResponder touchesBegan:touches withEvent:event]; 
    } else { 
     [self handleDoubleTap:touch]; 
    } 
} 

मेरे पास एक व्यू कंट्रोलर है। जैसा कि आप जानते हैं, यूआईआरएसस्पोन्डर से कंट्रोलर का वारिस देखें। वह व्यू कंट्रोलर एक MyView ऑब्जेक्ट बनाता है जो UIView से प्राप्त होता है, और इसे अपने स्वयं के दृश्य में एक सबव्यूव के रूप में जोड़ता है।

तो हमने:

देखें नियंत्रक> एक दृश्य (स्वतः)> एक MyView (जो एक UIView है) है।

अब माईव्यू के अंदर मैंने उस कोड को एनएसएलओजी के साथ ऊपर रखा है जो प्रिंट करता है "मेरा व्यू छुआ"। लेकिन मैं उपरोक्त की तरह, अगले उत्तरदाता को घटना को अग्रेषित करता हूं। और व्यू कंट्रोलर के अंदर मेरे पास एक और स्पर्श है, जो कि एक एनएसएलओजी ला ला "स्पर्श दृश्य नियंत्रक" प्रिंट करता है।

अब अनुमान लगाएं: जब मैं MyView को स्पर्श करता हूं, तो यह "MyView को छुआ" प्रिंट करता है। जब मैं MyView के बाहर स्पर्श करता हूं, जो वीसी का दृश्य है, तो मुझे "स्पर्श दृश्य नियंत्रक" मिलता है। तो दोनों काम करते हैं! लेकिन काम नहीं करता है घटना को अग्रेषित कर रहा है। क्योंकि अब, वास्तव में अगला उत्तरदाता दृश्य नियंत्रक होना चाहिए, क्योंकि इसमें कुछ भी नहीं है। लेकिन वीसी की इवेंट हैंडलिंग विधि को कभी भी कॉल नहीं किया जाता है जब मैं इसे अग्रेषित करता हूं।

% $ &! § !!

विचार?

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

उत्तर

5

similar question के अनुसार, आपकी विधि को काम करना चाहिए।

यह, की ओर जाता है मुझे लगता है कि अपने दृश्य के nextResponderनहीं वास्तव में ViewController है के रूप में यदि आपको संदेह है।

if (numTaps < 2) { 
    NSLog(@"nextResponder = %@", self.nextResponder); 
    [self.nextResponder touchesBegan:touches withEvent:event]; 
} 

तुम भी इतना है कि वे उत्पादन के आधार पर अपनी अन्य NSLog संदेशों को बदलने और जानकारी पता कर सकते हैं:

मैं क्या आपके nextResponder वास्तव में अंक के लिए जाँच करने के लिए अपने अग्रेषण कोड में एक त्वरित NSLog जोड़ना होगा

NSLog(@"touched %@", self); 

touched <UIView 0x12345678>

यह आपको समस्या का निदान करने के लिए शुरू करना चाहिए।

+0

धन्यवाद eJames। MyView मुझे बताता है कि अगला उत्तरदाता दृश्य नियंत्रक का बिल्कुल सही दृश्य है। मेमोरी एड्रेस सही मिलान करता है। हालांकि, यह स्पर्श बेगन नहीं कहा जाएगा। लेकिन अब मैं देखता हूं कि इस विधि को व्यू कंट्रोलर के दृश्य पर बुलाया जाएगा, लेकिन दृश्य नियंत्रक पर ही नहीं। लेकिन फिर, क्या यह घटना दृश्य के दृश्य नियंत्रक को बुलबुला जारी नहीं रखेगी, इसे संभाल नहीं पाती है? या यह एक और विशेष मामला है क्योंकि मैं इसे मैन्युअल रूप से भेजता हूं? –

+0

ठीक है, मुझे लगता है कि यह समझ में आता है। 'TouchesBegan: 'का डिफ़ॉल्ट कार्यान्वयन कुछ भी नहीं करता है, इसलिए जब आप इसे अगले' UIView' ऑब्जेक्ट पर भेज देते हैं, तो यह बस समाप्त होता है। क्या टच इवेंट को देखने के लिए मैन्युअल रूप से दृश्य नियंत्रक को पास करना संभव है? –

+0

क्या आपने '[self.nextResponder touchesBegan: ...] 'के बजाय' [सुपर स्पर्श बेगन: ...] 'को कॉल करने का प्रयास किया है, मैंने कुछ लोगों को उस विधि का उपयोग करके देखा है, लेकिन मुझे यकीन नहीं है कि यह क्या करता है। –

2

हां इसे सामान्य मामले में 100% काम करना चाहिए। मैंने अभी परीक्षण परियोजना के साथ प्रयास किया है और सबकुछ ठीक लगता है।

मैंने व्यू-आधारित एप्लिकेशन बनाया है। इंटरफ़ेस बिल्डर का उपयोग करके वर्तमान दृश्य में नया UIView डालें।फिर UIView के उप-वर्ग के साथ नई फ़ाइल बनाएं और मेरे नए दृश्य के लिए केवल बनाई गई कक्षा का चयन करें। (इंटरफ़ेस बिल्डर-> कक्षा पहचान-> कक्षा-> MyViewClass)

MyViewClass और UIViewController दोनों के लिए हैंडलर फ़ंक्शंस स्पर्श करें।

// MyViewClass

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
NSLog(@"myview touches"); 
[self.nextResponder touchesBegan:touches withEvent:event]; 
} 

// ViewController

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    NSLog(@"controller touches"); 
} 

मैं दोनों NSLogs जब प्रेस MyViewClass देखते हैं। क्या आपने अपना व्यू कंट्रोलर लोड करते समय इंटरफ़ेस बिल्डर और एक्सआईबी फ़ाइल का उपयोग किया है या loadView फ़ंक्शन के साथ प्रोग्रामेटिक रूप से सेट सेट किया है?

1

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

4

इस के साथ परेशानी थी, क्योंकि मेरा कस्टम दृश्य दृश्य पदानुक्रम में गहरा था। इसके बजाय, मैंने उत्तरदायी श्रृंखला पर चढ़ाई की जब तक कि यह UIViewController नहीं पाता;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    // Pass to top of chain 
    UIResponder *responder = self; 
    while (responder.nextResponder != nil){ 
     responder = responder.nextResponder; 
     if ([responder isKindOfClass:[UIViewController class]]) { 
      // Got ViewController 
      break; 
     } 
    } 
    [responder touchesBegan:touches withEvent:event]; 
} 
2

एक दृश्य नियंत्रक संदर्भ के लिए, आप क्योंकि [self nextResponder] एक दृश्य नियंत्रक का दृष्टिकोण और [[self nextResponder] nextResponder] मतलब है दृश्य नियंत्रक ही मतलब है

[[self nextResponder] nextResponder] 

उपयोग करने की आवश्यकता है, अब आप स्पर्श घटना प्राप्त कर सकते हैं

+0

आईओएस 9 और 10 में अच्छी तरह से काम कर सकता है लेकिन आईओएस 11 में काम नहीं करता है । जब तक आप व्यू कंट्रोलर या टेबल व्यू कंट्रोलर तक नहीं पहुंच जाते, तब तक आपको वास्तव में प्रतिक्रियाकर्ता श्रृंखला पर चढ़ने की आवश्यकता होती है। – ghr

1

आज मुझे इस तरह के प्रश्न या इस तरह के प्रश्न को ठीक करने के लिए एक बेहतर तरीका मिला। तब तुम्हारा UITableViewController में

@protocol imageViewTouchDelegate 

-(void)selectedFacialView:(NSInteger)row item:(NSInteger)rowIndex; 

@end 

@property(nonatomic,assign)id<imageViewTouchDelegate>delegate; 

:

तुम्हारा UITableViewCell में, आप एक प्रतिनिधि के स्पर्श घटना सुनने के लिए जोड़ सकते हैं, इस तरह इस तरह से किया अपना सकते हैं:

@interface pressionTable : UITableViewController<facialViewDelegate> 

और में .m फ़ाइल आप इस प्रतिनिधि इंटरफ़ेस को लागू कर सकते हैं, जैसे:

-(void)selectedFacialView:(NSInteger)row item:(NSInteger)rowIndex{ 
//TO DO WHAT YOU WANT} 

नोट: जब आप init सेल, आप प्रतिनिधि सेट करना होगा, अन्यथा प्रतिनिधि अमान्य है, तो आप की तरह इस

- (UITableViewCell *)tableView:(UITableView *)tableView 
    cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

static NSString *CellIdentifier = @"Cell"; 

pressionCell *cell = (pressionCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
if (cell == nil) { 
    cell = [[pressionCell alloc]initWithFrame:CGRectMake(0, 0, 240, 40)]; 
} 

cell.delegate = self; 

}

पी एस कर सकते हैं: मैं जानता हूँ कि इस डॉक्टर पुराना है, लेकिन मैं अभी भी ठीक करने के लिए मेरी विधि जोड़ें सवाल यह है कि जब लोग एक ही समस्या को पूरा करते हैं, तो उन्हें मेरे उत्तर से सहायता मिल जाएगी।

2

आप UIResponder के प्रलेखन को देखें, तो विवरण का कहना है कि डिफ़ॉल्ट रूप से:

UIView UIViewController उद्देश्य यह है कि यह प्रबंधन करता है वापस लौट कर इस पद्धति को लागू करता है (अगर यह एक है) या इसके superview (अगर यह नहीं करता है 'टी);

यदि आपका दृश्य व्यू कंट्रोलर वापस नहीं कर रहा है, तो उसे इसके पर्यवेक्षण को वापस लौटना होगा (जैसा आपने पाया था)।

- (BOOL)sendAction:(SEL)action 
       to:(id)target 
       from:(id)sender 
      forEvent:(UIEvent *)event 

जब से तुम लक्ष्य के लिए एक संदर्भ की जरूरत नहीं है, तो आप अपने तरीके से प्रत्युत्तर श्रृंखला लक्ष्य निर्धारित करके काम कर सकते हैं:

UIApplication वास्तव में एक विधि है कि वास्तव में उपयोग के इस मामले को संभालने के लिए माना जाता है है nil के रूप में मूल्य प्रलेखन के अनुसार के बाद से:

यदि लक्ष्य नहीं के बराबर है, एप्लिकेशन संदेश पहले प्रत्युत्तर करने के लिए, जिस कारण से से यह प्रत्युत्तर श्रृंखला की प्रगति जब तक यह नियंत्रित किया जाता है भेजता है।

आप निश्चित रूप से अपने वर्ग विधि [UIApplication sharedApplication]

अधिक जानकारी यहाँ के साथ UIApplication तक पहुँच प्राप्त कर सकते हैं: UIApplication documents

इस अतिरिक्त है, लेकिन आप पूरी तरह से दृश्य नियंत्रक का उपयोग की जरूरत है अगर कुछ एक करने के लिए थोड़ा अधिक जटिल, जब तक आप व्यू कंट्रोलर नहीं लौटाते, तब तक nextResponder विधि को कॉल करके दृश्य नियंत्रक तक पहुंचने तक आप प्रतिक्रियाकर्ता श्रृंखला को मैन्युअल रूप से अपना रास्ता बना सकते हैं। उदाहरण के लिए:

UIResponder *responder = self; 
while ([responder isKindOfClass:[UIView class]]) 
    responder = [responder nextResponder]; 

तो आप बस इसे अपने दृश्य नियंत्रक के रूप में डाली और जो कुछ भी आप इसके साथ करना चाहता था कर आगे बढ़ सकते हैं:

UIViewController *parentVC = (UIViewController *)responder 
संबंधित मुद्दे

 संबंधित मुद्दे