2010-10-31 14 views
13

Sono sicuro che questo è nella documentazione di Apple o deve essere stato risposto da qualche parte su questo forum, poiché sembra così semplice, ma non riuscivo a trovarlo né una soluzione particolarmente elegante me stesso.Memorizzare il contenuto di UITextField prima del pop di visualizzazione

Quello che ho è un UIViewController che spinge una vista di modifica sul suo stack di navigazione. La vista di modifica contiene un sacco di campi UIText. Se uno di questi è in fase di modifica quando viene toccato il pulsante Indietro, il metodo ViewWillAppear della vista originale viene chiamato prima dei metodi delegati UITextField di textFieldShouldEndEditing o textFieldDidEndEditing o il metodo textFieldEditingEnded dell'azione collegata IB viene chiamato.

Ecco alcuni codice che spero possa renderlo più chiaro:

Nella UIViewController:

- (void) viewWillAppear: (BOOL) animated { 
    [super viewWillAppear: animated]; 
    NSLog(@"Entering view will appear for master view"); 
    nameLabelField.text = objectToEdit.name; 
} 
- (IBAction) editMyObject: (id) sender { 
    NSLog(@"Editing the object"); 
    EditViewController *evc = [[EditViewController alloc] initWithNibName: @"EditTableView" bundle: nil]; 
    evc.editedObject = objectToEdit; 
    [self.navigationController pushViewController: evc animated: YES]; 
    [evc release]; 
} 

Nel EditViewController < UITextFieldDelegate>:

- (void) viewWillAppear: (BOOL) animated { 
    [super viewWillAppear: animated]; 
    nameField.text = editedObject.name; 
} 
- (void) viewWillDisappear: (BOOL) animated { 
    [super viewWillDisappear: animated]; 
    NSLog(@"In viewWillDisappear"); 
    if([self.navigationController.viewControllers indexOfObject: self] == NSNotFound) { 
     NSLog(@"-- We are not in controller stack... the back button has been pushed"); 
    } 
} 
- (BOOL) textFieldShouldEndEditing: (UITextField *) textField { 
    NSLog(@"In textFieldShouldEndEditing"); 
    // Store text field value here??? 
    // editedObject.name = nameField.text; 
    return YES; 
} 
- (void) textFieldDidEndEditing: (UITextField *) textField { 
    NSLog(@"In textFieldDidEndEditing"); 
    // Store text field value here??? 
    // editedObject.name = nameField.text; 
} 
- (IBAction) textFieldEditingEnded: (id) sender { 
    NSLog(@"In textFieldEditingEnded"); 
    // Store text field value here??? 
    // editedObject.name = nameField.text; 
} 

Il registro finisce con :

[...] Entrare vista appare per la vista maestro
[...] Modifica l'oggetto
[...] In viewWillDisappear
[...] - Non siamo in pila di controllo .. . il tasto posteriore è stato spinto
[...] Entrare vista apparirà per la vista maestro
[...] In textFieldShouldEndEditing
[...] In textFieldEditingEnded
[...] In textFieldDidEndEditing

Voglio impostare self.editedObject.name = nameField.text prima che l'etichetta venga impostata su viewWillAppear per UIViewController.

Ho pensato al metodo viewWillDisappear per il controllo di EditViewController per vedere se qualcuno dei miei campi di testo è attualmente il primo risponditore e in tal caso ottenere il loro testo e archiviarlo, ma questo sembra un tale kludge che sarà un dolore per mantenere se aggiungo o cambio campi di testo.

Posso anche implementare l'azione collegata textFieldEditingChanged IB per impostare il testo nell'oggetto modificato dopo ogni sequenza di tasti, ma questo è anche un bel po 'di overhead dato che devo capire quale campo di testo sono in ogni sequenza di tasti (ricordate che mostrava solo name ma ce ne sono un sacco).

Tutto ciò di cui ho bisogno è che la modifica sia terminata o sapere che la modifica sarà terminata prima che viewWillAppear venga chiamato in UIViewController in modo che il nomeFieldLabel sia impostato correttamente.

risposta

17

OK, ho capito una soluzione semplice dopo un sacco di web-surfing, la lettura forum, e la lettura manuale. Era, come sospettavo, molto semplice, solo una riga di codice aggiunta. Nel metodo del EditViewContorller viewWillDisappear ho aggiunto semplicemente:

[self.view.window endEditing: YES]; 

Ora textFieldShouldEndEditing, textFieldEditingEnded e textFieldDidEndEditing tutte licenziato fuori prima della viewWillAppear della vista maestro fa.

Così ora il metodo viewWillDisappear assomiglia:

- (void) viewWillDisappear: (BOOL) animated { 
    [super viewWillDisappear: animated]; 
    NSLog(@"In viewWillDisappear"); 
    // Force any text fields that might be being edited to end so the text is stored 
    [self.view.window endEditing: YES]; 
} 

E i metodi già in atto per gestire il 'ritorno' sulla tastiera gestire anche il pulsante 'Indietro' sul controller di navigazione.

Grazie mille Aaron e Jeff per la vostra assistenza e aiutandomi a riflettere su questo.

+0

Grazie per la risposta. Ho trovato anche la risposta a questa domanda: http://stackoverflow.com/questions/11319144/ios-xcode-crashed-after-typing-in-texts-in-uitextfield-and-go-back-nsisobject/ 11364617 # 11364617 – zekel

+0

Grazie mille! Questo mi stava facendo impazzire. Intuitivamente, mi piacerebbe vederlo come comportamento predefinito. – guptron

+0

Questo non funziona per me, il seguito avviene prima di 'viewWillDisappear': ( – RnMss

0

Perché non creare il proprio pulsante Indietro con quella logica nel suo metodo di azione?

+0

Grazie per il suggerimento Jeff. Questo potrebbe essere ciò che devo fare, ma perdo l'interfaccia utente nativa del pulsante con la punta appuntita, a meno che non esegua molto lavoro creando un pulsante personalizzato creando un file PNG per esso, ecc., Ecc., I Sono disposto a farlo se devo, al fine di ottenere la funzionalità, ma spero in qualcosa che mi manca solo aggiungere al mio codice. – LavaSlider

-1

Penso che da una prospettiva UX, dovresti visualizzare un avviso per determinare se l'utente vuole annullare l'azione di modifica che erano nel mezzo prima di uscire dalla vista corrente.

Avvisando l'utente, è possibile vedere se ha colpito il pulsante per sbaglio o se ha deciso di lasciare la vista, prendere l'azione appropriata.

// add this to the field(s) to be edited, selector will be called as the changes 
// are being made... still difficult to handle a cancel, but should work 
[objectToEdit addTarget:self action:@selector(updateNameField:) 
         forControlEvents:UIControlEventEditingChanged]; 

codice aggiuntivo qui ...

// the method called to update object from parent view 
- (void)updateNameField:(id)sender { 
    <OBJECT TO UPDATE>.text = ((UITextField *)sender).text; 
} 
+0

Sarei OK con quello. Stavo davvero pensando che sarebbe stato un pulsante indietro intenzionale ... perché colpire Done e Back? Suppongo che questo richieda "Back" accidentali. Ma questo non fornisce alcun aiuto dal momento che non ho un modo di sapere se presentare l'avviso poiché non so cosa o se un campo di testo è in fase di modifica. – LavaSlider

+0

@LavaSlider vedere le modifiche, per fare qualcosa come textFieldEditingChanged che stavi discutendo –

+0

@LavaSlider non troppo difficile per implementare qualcosa come textFieldEditingChanged. Vedi le modifiche di cui sopra per la soluzione –

Problemi correlati