7

Una cosa che ho sempre avuto problemi con Cocoa Bindings è stata la presentazione degli errori, ad esempio quando l'utente digita il valore sbagliato in un campo di testo con un formattatore allegato. Normalmente sostituisco lo willPresentError: da qualche parte nella catena di risposta, ma il mio problema è che gli oggetti NSError creati dal sistema Bindings non contengono informazioni sufficienti per dire cosa non è riuscito, o se è anche un errore che mi interessa personalizzare. Potrei rimuovere completamente i binding dall'equazione e creare i miei errori quando si verificano problemi di convalida, ma mi sento come se stessi buttando fuori alcune cose utili in questo modo.Come sovrascrivere la presentazione NSError quando sono coinvolti i bind?

Sono stato in grado di aggirare questo implementando i metodi dei delegati NSControl e memorizzando il controllo che non è riuscito in una variabile di istanza nel mio controller di visualizzazione. Se non è nulla per il momento in cui willPresentError: ruota intorno, so cosa non è riuscito a convalidare.

- (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)string errorDescription:(NSString *)error; 
{ 
    _errorSender = [control retain]; 
    return NO; 
} 

- (NSError *)willPresentError:(NSError *)error; 
{ 
    if (_errorSender != nil) 
    { 
     NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:[error userInfo]]; 
     NSString *help = NSLocalizedString(@"Why are you always messing up? You are a terrible person.", @""); 

     [_errorSender release]; 
     _errorSender = nil; 
     [userInfo setObject:help forKey:NSLocalizedRecoverySuggestionErrorKey]; 

     return [NSError errorWithDomain:[error domain] code:[error code] userInfo:userInfo]; 
    } 

    return [super willPresentError:error]; 
} 

questo funziona quando i primi cambiamenti responder, ma non quando chiamo commitEditing sul controller della vista, quindi è solo parzialmente utile per me.

L'unica altra opzione che posso vedere è quella di eliminare NSFormatter dall'equazione e utilizzare validateValue:forKey:error: negli oggetti gestiti di Dati principali per gestire la convalida. Questo non ha senso per me quanto usare un formattatore, ma almeno avrei il controllo completo sull'oggetto NSError.

Mi sento come se mi dovessi perdere qualcosa perché ci fosse questo tipo di disconnessione con la gestione degli errori. Eventuali suggerimenti?

risposta

4

I could completely remove bindings from the equation and create my own errors when validation problems occur, but I feel like I would be throwing out some useful stuff that way.

È possibile utilizzare NSUnderlyingErrorKey per avvolgere un errore (l'oggetto per quella chiave) in un altro errore (quello il cui userInfo contiene quella chiave).

The only other option I can see is taking NSFormatter out of the equation, and using validateValue:forKey:error: in my Core Data managed objects to handle validation. This doesn't make as much sense to me as using a formatter, but at least I'd have full control over the NSError object.

Questi sono due livelli separati e non si escludono a vicenda. La convalida del formattatore è a livello di vista; la convalida valore-chiave (in questo caso, negli oggetti gestiti) si trova nel livello del modello.

Se la convalida in questione deve avvenire a livello di vista, sottoclasse la classe NSFormatter (se non lo hai già) e attua getObjectValue:forString:errorDescription: per restituire una descrizione di errore più specifica. (Non ho idea se Attacchi in realtà utilizza questa descrizione dell'errore, però. Si dovrebbe controllare.)

Se la convalida deve avvenire a livello di modello, implementare validate<Key>:error: (la versione single-proprietà di validateValue:forKey:error:) nella sottoclasse NSManagedObject.

Se alcuni dei vincoli sono a livello di modello e altri a livello di vista, eseguire entrambi. Sei libero di implementare alcuni controlli nel formattatore e altri controlli nel modello, se questo ha senso per la tua app e i tuoi assegni.

+1

Sto sottoclassi NSFormatter e mentre i binding utilizzano il messaggio di errore NSString, fornisco l'ultimo NSAlert è ancora abbastanza semplice (vorrei aggiungere un suggerimento di recupero all'errore, come minimo). La convalida che sto facendo sembra che sia più adatta alle sottoclassi NSFormatter, motivo per cui sono titubante nell'implementare la convalida del valore-chiave sul mio modello. Finirei per fare tutti i tipi di parsing di stringhe che non hanno nulla a che fare con il modello di dati, solo per essere in grado di personalizzare il messaggio di errore front-end quando qualcosa va storto. –

Problemi correlati