2012-08-05 5 views
13

मैं एक साधारण एप्लिकेशन लिख रहा हूं जिसमें 3 व्यू कंट्रोलर हैं। रूट व्यू कंट्रोलर item listing, मूल तालिका दृश्य है। इस दृश्य नियंत्रक के बाहर, मैं कुछ उपयोगकर्ता इंटरैक्शन के आधार पर दो अलग-अलग दृश्य नियंत्रकों को धक्का देता हूं - एक create item नियंत्रक देखें या view item नियंत्रक देखें।रूट व्यू कंट्रोलर पर वापस कैसे पॉप करें लेकिन फिर एक अलग दृश्य पर धक्का दें?

तो, स्टोरीबोर्ड सीग्स सिर्फ वी, या कुछ जैसा दिखता है।

मेरे create item पर नियंत्रक देखें, मैं इसे रूट व्यू कंट्रोलर पर वापस पॉप करना चाहता हूं, जब उपयोगकर्ता कोई नया आइटम बनाता है, लेकिन फिर view item नियंत्रक को दबाएं ताकि मैं नव निर्मित आइटम को देख सकूं।

मुझे यह काम करने के लिए प्रतीत नहीं होता है। रूट व्यू कंट्रोलर पर वापस पॉप करना काफी आसान है, लेकिन मैं view item नियंत्रक को धक्का देने में असमर्थ हूं।

कोई विचार? मैंने नीचे अपना कोड चिपकाया है। पॉप फ़ंक्शन काम करता है, लेकिन नया दृश्य कभी प्रकट नहीं होता है।

- (void) onSave:(id)sender { 

    CLLocation *currentLocation = [[LocationHelper sharedInstance] currentLocation]; 

    // format the thread object dictionary 
    NSArray* location = @[ @(currentLocation.coordinate.latitude), @(currentLocation.coordinate.longitude) ]; 
    NSDictionary* thread = @{ @"title": _titleField.text, @"text": _textField.text, @"author": @"mustached-bear", @"location": location }; 

    // send the new thread to the api server 
    [[DerpHipsterAPIClient sharedClient] postPath:@"/api/thread" 
             parameters:thread 
              success:^(AFHTTPRequestOperation *operation, id responseObject) { 

               // init thread object 
               Thread *thread = [[Thread alloc] initWithDictionary:responseObject]; 

               // init view thread controller 
               ThreadViewController *viewThreadController = [[ThreadViewController alloc] init]; 
               viewThreadController.thread = thread; 

               [self.navigationController popToRootViewControllerAnimated:NO]; 
               [self.navigationController pushViewController:viewThreadController animated:YES]; 

              } 
              failure:^(AFHTTPRequestOperation *operation, NSError *error) { 

               [self.navigationController popToRootViewControllerAnimated:YES]; 

              }]; 

} 
+0

मैं "आइटम बनाएं" और "आइटम देखें" के लिए अलग-अलग दृश्य नियंत्रक नहीं बनाएगा। यह सच है कि आप इसे बनाने के बाद आइटम देखना चाहते हैं, लेकिन हमेशा एक और संभावना है कि आपका उपयोगकर्ता इसे देखने के बाद आइटम को संपादित करना चाहें। एक दृश्य में निर्माण, देखने और संपादित करने की अनुमति देने के लिए एक दृश्य नियंत्रक को डिज़ाइन करना आसान होगा। अधिकांश ऐप्स इसे इस तरह से डिजाइन करते हैं। अपना समय चारों ओर segueing बचाओ। – Rick

उत्तर

6

एक आसान तरीका है पूरा करने के लिए आप क्या करना चाहते हैं कि आपके मुख्य जड़ दृश्य नियंत्रकों में कुछ सरल तर्क का निर्माण करना है। मूल रूप से रूट नियंत्रक के लिए "बैक रेफरेंस"। यहां एक त्वरित उदाहरण है।

मुख्य जड़ नियंत्रक (इस नियंत्रक एक पर विचार) - अच्छी तरह से इसे कहते में

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 
    self.jumpNeeded ? NSLog(@"jump needed") : NSLog(@"no jump needed"); 

    if (self.jumpNeeded) { 
     NSLog(@"jumping"); 
     self.jumpNeeded = NO; 
     [self performSegueWithIdentifier:@"controllerC" sender:self]; 
    } 
} 

में कूद स्थिति का ट्रैक रखने के

@property (nonatomic) BOOL jumpNeeded; 

सेटअप कुछ तर्क अब, एक गुण सेट controllerA आपका मुख्य रूट नियंत्रक, जब कोई टेबलव्यू पंक्ति चयनित होती है तो इस तालिका में नियंत्रक बी को दबाते समय जैसे कुछ ऐसा दृश्य देखें विधि

[self [email protected]"controllerB" sender:self]; 

तो लागू अपने segue विधि के लिए तैयार

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

    //setup controller B 
    if([segue.identifier isEqualTo:@"controllerB"]){ 
    ControllerB *b = segue.destinationViewController; 
    b.delegate = self; //note this is the back reference 
    } 

    //implement controller c here if needed 
} 

अब आप संदर्भ धारण करने के लिए एक संपत्ति "प्रतिनिधि" कहा जाता है निर्धारित करने की आवश्यकता controllerB पर चलते हैं और आप से हेडर फाइल आयात करने की आवश्यकता जड़ नियंत्रक

#import "controllerA" 

@property (nonatomic,weak) controllerA *delegate; 

तो बस से पहले आप controllerA को वापस पॉप, आप झंडा

सेट

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

+0

मैंने इसे उत्तर के रूप में चुना, क्योंकि प्रतिनिधियों ने मार्ग समाप्त किया था। हालांकि, मैंने पुश सेग्यू को सभी को एक साथ छोड़ दिया और 'आइटम बनाएं' दृश्य के लिए एक मोडल सेगू के साथ चला गया। – Ryan

+0

मुझे खुशी है कि युक्तियाँ आपको एक दिशा में जा रही हैं जो आपके लिए काम करती है। शुभकामनाएँ! – CocoaEv

0

मुझे नहीं लगता कि यह संभव है क्योंकि वापस पॉपिंग सब कुछ खराब कर देगा।

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

6

मुझे लगता है कि
[self.navigationController pushViewController:viewThreadController animated:YES]; कि पहले बयान से एक अलग navigationController उपयोग कर रहा है। क्योंकि आप ढीला नेविगेशन नियंत्रक आप में हैं जड़ दृश्य नियंत्रक को पॉपिंग के बाद। समाधान इस कोड का उपयोग करने के बजाय

UINavigationController *nav = self.navigationController; 
[self.navigationController popToRootViewControllerAnimated:NO]; 
[nav pushViewController:viewThreadController animated:YES]; 

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

+0

मेरी शिक्षाएं: एनिमेटेड का उपयोग करते समय: हाँ तो यह इरादे के रूप में काम नहीं करता है, लेकिन एनिमेटेड: नौकरी नहीं करता है। और चूंकि popToRoot छोटा है, मैंने इसका इस्तेमाल किया। आशा करता हूँ की ये काम करेगा! – kjoelbro

+0

बस popToRootController का उपयोग करना मेरा जवाब है।दृश्य के साथ मज़ेदार कुछ भी करने की ज़रूरत नहीं है नियंत्रक ढेर और धक्का सामान्य रूप से सामान्य काम कर सकते हैं। –

36

अगर मैं तुम्हें सही ढंग से समझ, आप दृश्य नियंत्रकों के एक ढेर है:

A (root) - B - C - D - E 

और आप इसे बनना चाहते हैं:

A (root) - F 

है न? उस मामले में: - (शून्य) viewWillAppear विधि और तर्क स्विच फ्लिप के लिए एक प्रतिनिधि कॉलबैक का उपयोग

NSArray *viewControllers = self.navigationController.viewControllers; 
NSMutableArray *newViewControllers = [NSMutableArray array]; 

// preserve the root view controller 
[newViewControllers addObject:[viewControllers objectAtIndex:0]]; 
// add the new view controller 
[newViewControllers addObject:viewThreadController]; 
// animatedly change the navigation stack 
[self.navigationController setViewControllers:newViewControllers animated:YES]; 
+0

यह एफ ई –

+2

^@LysannSchlegel को देखने के लिए दृश्य ई से एनिमेट करेगा। यह ई-> एफ से एनिमेट करता है, लेकिन फिर यदि आप बैक बटन दबाते हैं तो आप ई के बजाए ए पर जाएंगे। असल में, बैक स्टैक को पैरेंट व्यू को बिना किसी फंकी/अप्रत्याशित एनिमेशन के साफ़ कर दें! – DiscDev

+1

डेव का जवाब बहुत अच्छा है, इसे UINavigationController पर एक श्रेणी के साथ पुन: उपयोग के अगले स्तर पर ले जाएं: http://stackoverflow.com/a/25771209/1103584 – DiscDev

5

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

@implementation UINavigationController (PushNewAndClearNavigationStackToParent) 

- (void) pushNewControllerAndClearStackToParent:(UIViewController*)newCont animated:(BOOL)animated 
{ 
    NSArray *viewControllers = self.viewControllers; 
    NSMutableArray *newViewControllers = [NSMutableArray array]; 
     
    // preserve the root view controller 
    [newViewControllers addObject:[viewControllers firstObject]]; 
    // add the new view controller 
    [newViewControllers addObject:newCont]; 
    // animatedly change the navigation stack 
    [self setViewControllers:newViewControllers animated:animated]; 
} 

@end 
1
NSArray *viewControllers = self.navigationController.viewControllers; 
NSMutableArray *newViewControllers = [NSMutableArray array]; 

// preserve the root view controller 
for(int i = 0; i < [viewControllers count];i++){ 
    if(i != [viewControllers count]-1) 
     [newViewControllers addObject:[viewControllers objectAtIndex:i]]; 
} 
// add the new view controller 
[newViewControllers addObject:conversationViewController]; 
// animatedly change the navigation stack 
[self.navigationController setViewControllers:newViewControllers animated:YES]; 
+0

क्या आप अपने समाधान को आपके द्वारा प्रदान किए गए समाधान के बारे में थोड़ा और विवरण जोड़कर विस्तारित कर सकते हैं? – abarisone

0

मैं प्रेरणा के रूप में डेव के जवाब का इस्तेमाल किया और स्विफ्ट के लिए यह बनाया:

let newViewControllers = NSMutableArray() 
newViewControllers.addObject(HomeViewController()) 
newViewControllers.addObject(GroupViewController()) 
let swiftArray = NSArray(array:newViewControllers) as! Array<UIViewController> 
self.navigationController?.setViewControllers(swiftArray, animated: true) 
  1. HomeViewController() जो कुछ भी आप अपने नीचे दृश्य नियंत्रक होने के लिए
  2. बदलें GroupViewController चाहते बदलें() जो कुछ भी आप चाहते हैं उसके शीर्ष नियंत्रक
0

यदि आप एक ही नेविगेशन नियंत्रक के अंदर किसी भी तरह से नेविगेट करना चाहते हैं ... आप नेविगेशनस्टैक एके.ए. तक पहुंच सकते हैं। ViewControllers और उसके बाद दृश्य नियंत्रक को क्रम में सेट करें, या कुछ जोड़ें या हटाएं ... यह करने का यह सबसे साफ और मूल तरीका है।

 UINavigationController* theNav = viewControllerToDismiss.navigationController; 
     UIViewController* theNewController = [UIViewController new]; 
     UIViewController* rootView = theNav.viewControllers[0]; 
     [theNav setViewControllers:@[ 
            rootView, 
            theNewController 
            ] animated:YES]; 

कोई आवश्यक सत्यापन करें ताकि आपको कोई अपवाद न हो।

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