2011-10-13 13 views
15

मैं एक आईओएस 5 आईपैड ऐप के लिए पॉपओवर पेश करने के लिए UIStoryboardPopoverSegue का उपयोग कर रहा हूं। Segue बहुत अच्छा काम करता है, लेकिन ऐसा लगता है कि टूलबार में पॉपओवर नियंत्रक के लिए एक पासथ्रू व्यू है, इसलिए यदि आप बटन दबाते रहते हैं, तो अधिक पॉपओवर दिखाई देते हैं। चूंकि मैं UIPopoverController का ट्रैक नहीं बना रहा हूं और खुद को ट्रैक कर रहा हूं (जैसे स्टोरीबोर्ड इसे कर रहा है) बटन को फिर से स्पर्श होने पर मैं इसे बर्खास्त नहीं कर सकता। क्या कोई और इस में चला है? मेरे पास ऐप्पल के साथ एक बग खुला है लेकिन उन्होंने जवाब नहीं दिया है।UIStoryboardPopoverSegue बटन स्पर्श पर एकाधिक विंडो खोलने

संपादित करें: मैंने इसे नीचे दिए गए उत्तर का उपयोग करके हल किया है। यहां कोड है जिसका उपयोग मैंने समाप्त किया था। currentPopover मेरे व्यू कंट्रोलर क्लास में __weak इवर है, इसलिए जब नियंत्रक किया जाता है तो यह स्वचालित रूप से शून्य हो जाएगा।

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ 
    if([segue isKindOfClass:[UIStoryboardPopoverSegue class]]){ 
     // Dismiss current popover, set new popover 
     [currentPopover dismissPopoverAnimated:YES]; 
     currentPopover = [(UIStoryboardPopoverSegue *)segue popoverController]; 
    } 
} 
+0

आपके संपादन के लिए धन्यवाद, समस्या का एक सुंदर समाधान! – shapecatcher

उत्तर

2

आप popoverController संपत्ति prepareForSegue वर्ग विधि में UIStoryboardPopoverSegue वर्ग का हिस्सा के रूप में पारित करने के लिए एक संदर्भ के स्टोर करने के लिए किया है।

इसे उपयोग करने के लिए, इस तरह बुला दृश्य नियंत्रक में विधि-सवारी:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    // The Storyboard Segue is named popover in this case: 
    if ([segue.identifier compare:@"popover"] == NSOrderedSame) { 
     // segue.popoverController is only present in popover segue's 
     // self.seguePopoverController is a UIPopoverController * property. 
     self.seguePopoverController = segue.popoverController; 
    } 
} 

तो फिर तुम यह हमेशा की तरह खारिज कर सकते हैं।

+0

जबकि मैं ऐप्पल से कुछ और अधिक स्वचालित करने की उम्मीद कर रहा था, यह काम करता है। मैंने उस कोड को जोड़ा है जिसे मैंने अपनी मूल पोस्ट में रुचि रखने वाले किसी भी व्यक्ति के लिए इस्तेमाल किया है। –

+0

कमाल! आईओएस 8.2 के साथ आईपैड पर चल रहे आईओएस 7 के लिए संकलित कोड पर यह दृष्टिकोण क्रैश हो गया है। आपको पॉपओवर को खारिज करने के लिए अनजान सेग का उपयोग करना होगा। धन्यवाद सेब। – SpaceDog

0

यह भी अच्छा है।

@interface ViewController : UIViewController <UIPopoverControllerDelegate> { 
    UIPopoverController * seguePopoverController; 
} 

@property (strong) UIPopoverController * seguePopoverController; 

@end 

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if (self.seguePopoverController) { 
     [self.seguePopoverController dismissPopoverAnimated:NO]; 
     self.seguePopoverController = nil; 
    } 

    // The Storyboard Segue is named popover in this case: 
    if ([[segue identifier] isEqualToString:@"popover"]) { 

     UIStoryboardPopoverSegue* popSegue = (UIStoryboardPopoverSegue*)segue; 
     UIPopoverController *thePopoverController = [popSegue popoverController]; 
     thePopoverController.delegate = self; 
     self.seguePopoverController = thePopoverController; 

    } 
} 

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController 
{ 
    self.seguePopoverController = nil; 
} 
+0

यदि आप प्रश्न में जोड़े गए कोड का उपयोग करते हैं, तो कमजोर ivar स्वचालित रूप से शून्य हो जाएगा जो उस कोड के समूह की आवश्यकता को मिटा देगा। यदि आप एक और पॉपओवर सेग्यू जोड़ते हैं और इसे "पॉपओवर" नाम देना भूल जाते हैं तो कोड अप टॉप भी काम करेगा। –

7

आपके समाधान कोरी के साथ कुछ दृश्य समस्याएं हैं।

दो विकल्प जिन्हें माना जा सकता है - पॉपओवर प्रस्तुत करने वाले बटन की कार्रवाई को हटा या बदलें।

विकल्प 1, बटन की कार्रवाई में पॉइंटर रखें, और पॉपओवर प्रस्तुत होने के बाद, कार्रवाई को शून्य पर सेट करें। मूल कार्रवाई में पॉपओवर रीसेट की बर्खास्तगी पर।

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 

    action = [sender action]; 
    [sender setAction:nil]; 

    self.currentPopover = [(UIStoryboardPopoverSegue *)segue popoverController]; 
    self.currentPopover.delegate = self; 
} 

-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController 
{ 
    [self.navigationItem.rightBarButtonItem setAction:action]; 

    return YES; 
} 

इस प्रकार पॉपओवर केवल एक बार दिखाई दे सकता है, और उम्मीद के रूप में खारिज कर दिया जाएगा।

बटन का फ़ंक्शन बदलने का दूसरा विकल्प होगा ताकि जब पॉपओवर दिखाई दे, तो बटन टैप करने से पॉपओवर को खारिज कर दिया जाएगा।

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
    { 

     action = [sender action]; 
     target = [sender target]; 

     [sender setTarget:self]; 
     [sender setAction:@selector(dismiss:)]; 

     self.currentPopover = [(UIStoryboardPopoverSegue *)segue popoverController]; 
     self.currentPopover.delegate = self; 
    } 

-(void)dismiss:(id)sender 
{ 
    [self.navigationItem.rightBarButtonItem setAction:action]; 
    [self.navigationItem.rightBarButtonItem setTarget:target]; 
    ////or 
// [sender setAction:action]; 
// [sender setTarget:target]; 
    [self.currentPopover dismissPopoverAnimated:YES]; 
} 


    -(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController 
    { 
     [self.navigationItem.rightBarButtonItem setAction:action]; 
     [self.navigationItem.rightBarButtonItem setTarget:target]; 

     return YES; 
    } 
+0

रॉबर्ट का समाधान मेरे लिए बिल्कुल ठीक काम करता है। मुझे लगता है कि इस प्रकार सेब UISplitViewController में इस तकनीक को लागू करता है। बस एक ऐड-ऑन, आपको दो ivars जोड़ने की आवश्यकता है: एसईएल कार्रवाई; आईडी टर्गर; चीयर्स! – Raunak

+0

बढ़िया! एकमात्र चीज जो मैं इसमें जोड़ूंगा वह एक और ivar है: id myPopButton, और इसे तैयार करने के लिए सेट करें ForSegue: myPopButton = प्रेषक; इस तरह, आप एकाधिक बटनों को संदर्भित कर सकते हैं (जब टूलबार से कहा जाता है, 'frinstance)। 'खारिज' और 'popoverControllerShouldDismissPopover' विधियों में, कॉल करें: [myPopButton setAction: action]; और [myPop बटन सेट लक्ष्य: लक्ष्य]; इसका परीक्षण किया और यह बहुत अच्छा काम करता है (आईओएस एसडीके 6.0)। – mpemburn

2

इस समाधान में दृश्य समस्याएं भी हो सकती हैं, लेकिन यह मेरे साधारण मामले के लिए नहीं है। मेरे मामले में, पॉपओवर बस कुछ मदद प्रदर्शित कर रहा था। मैंने निम्नलिखित (एआरसी के साथ) को एक साथ रखा है जो पॉप बार व्यू कंट्रोलर को खारिज कर देगा जब बटन बार बटन दूसरी बार दबाया जाएगा (मूल और नव निर्मित दोनों)।

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if([segue isKindOfClass:[UIStoryboardPopoverSegue class]]) 
    { 
     UIStoryboardPopoverSegue *popoverSegue  = (id)segue; 
     UIPopoverController  *popoverController = popoverSegue.popoverController; 

     if(m_popoverController.popoverVisible) 
     { 
      [m_popoverController dismissPopoverAnimated:NO]; 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       [popoverController dismissPopoverAnimated:YES]; 
      }); 
      m_popoverController = nil; 
     } 
     else 
      m_popoverController = popoverController;   
    }  
} 

मैं भी dealloc

- (void)dealloc 
{ 
    if(m_popoverController.popoverVisible) 
     [m_popoverController dismissPopoverAnimated:YES]; 
} 

में कुछ सफाई जोड़ा यह अपनी कक्षा में एक सदस्य चर की आवश्यकता होती है

UIPopoverController *m_popoverController; 
3

आप कनेक्ट IBAction के माध्यम से एक UIBarButtonItem।itendifier इंटरफ़ेस बिल्डर में सेट का उपयोग करें:

UIPopoverController *currentPopoverController; 
:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 
    if ([[segue identifier] isEqualToString:@"aSegueIdentifier"]) 
     currentPopoverController = [(UIStoryboardPopoverSegue *)segue popoverController]; 
} 

currentPopoverController एक उदाहरण चर, हेडर फाइल में परिभाषित किया गया है:

-(IBAction)barButtonItemPressed:(id)sender { 
    if (currentPopoverController && currentPopoverController.popoverVisible) { 
     [currentPopoverController dismissPopoverAnimated:YES]; 
     currentPopoverController = nil; 
    } else { 
     [self performSegueWithIdentifier:@"aSegueIdentifier" sender:sender]; 
    } 
} 

seque से नए UIPopoverCOntroller के संदर्भ जाओ

महत्वपूर्ण: सेक की एंकर संपत्ति को संबंधित UIBarButtonItem पर सेट किया जाना चाहिए!

+0

जब तक आप 'currentPopoverController' के प्रतिनिधि को' didDismiss 'पर अपना संदर्भ न दें, तब भी आपको यहां कई पॉपओवर समस्याएं मिलेंगी। [मेरा पसंदीदा वर्कअराउंड] (http://stackoverflow.com/a/10238581/957768) ज्यादातर इस तरह के समान है, लेकिन मैं 'currentPopoverController' को कमजोर संदर्भ देता हूं - इस तरह यह स्वचालित रूप से 'nil''d पर ध्यान दिए बिना पॉपओवर को कैसे खारिज कर दिया जाता है। – rickster

2

मैं एक स्थिर कमजोर चर, जो एक ही स्थान पर सब कुछ एक साथ रहता है का उपयोग करना पसंद:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if ([[segue identifier] isEqualToString:@"showSomething"]) { 
     static __weak UIPopoverController* currentPopover = nil; 
     [currentPopover dismissPopoverAnimated:NO]; 
     currentPopover = [(UIStoryboardPopoverSegue *)segue popoverController]; 
     // ... 
    } 
} 

एक अलग अतिरिक्त चर जोड़ने के लिए (कोई कारण नहीं है जब आप दृश्य नियंत्रक के कई उदाहरण हो जा रहे हैं ?), और इस तरह आप प्रत्येक() ब्लॉक के लिए एक अतिरिक्त चर जोड़ सकते हैं।

+0

चालाक समाधान – Nektarios

1

जून 14 2013

प्रश्न में संपादन के लिए धन्यवाद। व्यू कंट्रोलर को खारिज करने और पुनर्निर्माण करने के बजाय - प्रदर्शन और बैटरी चिंताओं से बचने के लिए और दृश्य नियंत्रक को खारिज करते समय फ्लैश को रोकें - पॉपओवर के दूसरे उदाहरण को पॉपिंग से रोकने के बारे में कैसे?

//place in view controller (tested iOS6+, iPad, iPhone) 
__weak UIPopoverController *popover; 
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 
    if([segue isKindOfClass:[UIStoryboardPopoverSegue class]] 
     && [segue.identifier isEqualToString:@"mySegue"]) //remember to change "mySegue" 
      popover = [(UIStoryboardPopoverSegue *)segue popoverController]; 
} 
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender { 
    if ([identifier isEqualToString:@"mySegue"]) //remember to change "mySegue" 
     return !popover; 
    else 
     return YES; 
} 
added checks to: http://stackoverflow.com/a/10238581/1705353 
+1

मुझे यह पसंद है। कोड को अपने मूल पोस्ट के संपादन से अपने कंधे कोड के साथ जोड़ सकते हैं और इससे मेरे संपादन कोड से थोड़ा अधिक दृष्टि से प्रसन्नता हो जाएगी। –

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