2011-11-29 12 views
16

Uso il metodo performSegueWithIdentifier:sender: per aprire un nuovo ViewController da un file storyboard in modo programmatico. Funziona come un fascino.È possibile utilizzare un ViewController esistente con PerformSegueWithIdentifier?

Ma ogni volta che viene chiamato questo metodo, viene creato un nuovo ViewController. È possibile utilizzare lo ViewController esistente, se è presente? Non trovo nulla su questo problema (apple-doc, Stack Overflow, ...).

Il problema è: Sulla creato ViewController all'utente di impostare una forma-Elements e se il ViewController sarebbe chiamato nuovamente, la forma-elementi ha le impostazioni iniziali :(

Tutto l'aiuto sarebbe apprezzato

.

Edit: apprezzo le tante risposte Nel frattempo, io non sono a conoscenza del progetto e non riesco a controllare le vostre risposte

+1

In base al pattern MVC, è necessario salvare i valori utente in qualsiasi oggetto condiviso o in NSUserDefaults. Quindi la tua domanda non è completamente giusta –

+0

Hai ragione, questa funzione non è al momento implementata e verrebbe in futuro! Questo avrebbe risolto il mio problema, ma la domanda è sempre la stessa, se un ViewController può essere riutilizzato con questo metodo? Non posso immaginare che questo non è possibile. – matzino

risposta

0

creare una proprietà per il controller

...
@property (nonatomic, weak) MyController controller; 

E utilizzare una sorta di inizializzazione differita in performSegueWithIdentifier:sender

if (self.controller == nil) 
{ 
self.controller = [MyController alloc] init] 
... 
} 

In questo caso, se il controllore è già stato creato, verrà riutilizzato.

+0

Grazie, ho controllato questo, ma non funziona per me. Non so quanto l'inizializzazione pigra funzioni nel contesto dal metodo di esecuzione? – matzino

0

Ho affrontato questo problema oggi e quello che ho fatto è creare manualmente il controller di visualizzazione e memorizzarne il riferimento. Quindi ogni volta che ho bisogno del controller, controllare prima se esiste. Qualcosa di simile a questo:

MyController *controller = [storedControllers valueForKey:@"controllerName"]; 

if (!controller) 
{ 
    controller = [[UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:NULL] instantiateViewControllerWithIdentifier:@"MyControllerIdentifierOnTheStoryboard"]; 

    [storedControllers setValue:controller forKey:@"controllerName"]; 
} 

[self.navigationController pushViewController:controller animated:YES]; 

Speranza che aiuta.

+0

Grazie per il vostro consiglio, sembra che questa soluzione funzionerà. Ho risolto il mio problema salvando l'input dell'utente come citato da d.lebedev. Spingi il viewcontroller con l'aiuto di navigationController, puoi invece utilizzare il metodo performSegueWithIdentifier? – matzino

7

Per riutilizzare un'istanza UIViewController esistente con un seguito, creare il seguito da zero e fornire la propria destinazione (esistente) (UIViewController). Non dimenticare di chiamare prepareForSegue: se necessario.

Ad esempio:

UIStoryboardSegue* aSegue = [[UIStoryboardSegue alloc] initWithIdentifier:@"yourSegueIdentifier" source:self destination:self.existingViewController] 
[self prepareForSegue:aSegue sender:self]; 
[aSegue perform]; 
+0

Da dove provengono altre proprietà del seguito con questo approccio, come lo stile di presentazione? – Benjohn

2

Seguendo codice rende controller della vista singoletto. Aggiungili all'implementazione del controller di visualizzazione di destinazione, quindi segue riutilizzerà lo stesso vc.

static id s_singleton = nil; 
+ (id) alloc { 
    if(s_singleton != nil) 
     return s_singleton; 
    return [super alloc]; 
} 
- (id) initWithCoder:(NSCoder *)aDecoder { 
    if(s_singleton != nil) 
     return s_singleton; 
    self = [super initWithCoder:aDecoder]; 
    if(self) { 
     s_singleton = self; 
    } 
    return self; 
} 
+0

Come gestite 'didReceiveMemoryWarning' con questo approccio? – expert

+0

s_singleton = nil; ? –

+0

Mi hai salvato! Grazie :) – KiNG

-1

È necessario rendere il Viewcontroller in una classe Singleton.

12

Utilizzare shouldPerforSegueWithIdentifier per consentire o meno di eseguire o per annullare il seguito e aggiungere manualmente il ViewController. Mantieni un puntatore nello prepareForSegue.

... intestazione

@property (strong, nonatomic) MyViewController *myVC; 

...implementazione

-(BOOL) shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender{ 
    if([identifier isEqualToString:@"MySegueIdentifier"]){ 
     if(self.myVC){ 
      // push on the viewController 
      [self.navigationController pushViewController:self.myVC animated:YES]; 
      // cancel segue 
      return NO; 
     } 
    } 
    // allow the segue to perform 
    return YES; 
} 


-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if([segue.identifier isEqualToString:@"MySegueIdentifier"]){ 
     // this will only be called the first time the segue fires for this identifier 
     // retian a pointer to the view controller 
     self.myVC = segue.destinationViewController; 
    } 
} 
0

Se si tratta di un'applicazione universale, standard di master-detail (che utilizza un UISplitViewController) allora può questo può essere ottenuto impostando la proprietà viewControllers sul nuovo controller di navigazione con il controller dettagli precedente, come di seguito. Altrimenti può essere fatto, ma è necessario un ulteriore passaggio per mettere il controller che si desidera riutilizzare all'interno di un controller di navigazione nella story board.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 
    if ([[segue identifier] isEqualToString:@"showDetail"]) { 
     NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; 
     NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath]; 
     UINavigationController* navigationController = (UINavigationController*)[segue destinationViewController]; 

     // retrieve previous detail controller. 
     DetailViewController* controller = self.detailViewController; 

     if(controller){ 
      // if we have an existing detail controller then set it on the navigation controller. 
      navigationController.viewControllers = @[controller]; 
     } 
     else{ 
      // this must be the first time, so store the detail view controller for next time, and we don't need to modify the navigation controller in this case. 
      controller = (DetailViewController *)[navigationController topViewController]; 
      self.detailViewController = controller; 
     } 

     // update the detail controller as normal. 
     [controller setDetailItem:object]; 
     controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem; 
     controller.navigationItem.leftItemsSupplementBackButton = YES; 
    } 
} 

C'è sovraccarico che v'è un controller dettaglio disarchiviato dallo storyboard ogni volta, e purtroppo la sua vista è anche caricato. Tuttavia è immediatamente deallocato, e nel modello di Apples il comportamento predefinito è un controller di dettaglio che viene caricato e gettato via in modo tale che, se non vengono infastiditi, è probabilmente sicuro farlo in quel modo.

Problemi correlati