2011-01-10 11 views
7

Sono appena iniziato con Mac App Development e finora tutto va bene, sto solo avendo problemi nel cercare di ottenere un NSTextField in modo che accetti solo i numeri per l'input.Limita l'input NSTextField a solo valori numerici? NSNumberformatter

Finora ho aggiunto un formattatore a NSTextField e l'ho impostato per consentire solo i decimali ora quando inserisco le lettere nel campo che ancora mi consente ma non consente al mio di fare clic fuori dalla cella una volta terminato.

Idealmente, vorrei che l'app non consentisse all'utente di digitare lettere e solo emettere un segnale acustico o non fare nulla.

Eventuali consigli o indicazioni su questo sarebbe grande

+0

È possibile creare una sottoclasse di NSTextField e monitorarne l'input, come mostrato qui: http://pagesofinterest.net/blog/2010/11/subclassing-nstextfield-to-allow-only-numbers/ –

risposta

8

sottoclasse NSNumberFormatter e implementare questo metodo:

- (BOOL)isPartialStringValid:(NSString **)partialStringPtr 
     proposedSelectedRange:(NSRangePointer)proposedSelRangePtr 
       originalString:(NSString *)origString 
     originalSelectedRange:(NSRange)origSelRange 
      errorDescription:(NSString **)error 
+0

Ciao Potresti spiegare di più su come potrei usare questo codice? Sto idealmente cercando di limitare l'input a numerico solo con l'eccezione di virgola e decimale, cioè gli utenti possono inserire 12.00 o 12.450 – MonkeyBlue

+0

Bene, hai letto i documenti su di esso? Dimmi cosa da loro non capisci –

+0

Grazie per la risposta Mike, ora ho implementato un NSFormatter personalizzato e posso limitare il testo a soli 10 caratteri usando: if ([* partialStringPtr length]> maxLength) {comunque sono ancora lottando su come posso limitare l'input ai numeri e un singolo punto decimale. Ci scusiamo per tutte le domande, come puoi dire sono molto nuovo a tutto questo. – MonkeyBlue

1

Invece di sottoclasse qualsiasi cosa, è possibile farlo con un metodo NSControlTextEditingDelegate nel vostro controller della vista. Impostare il campo delegate dello NSTextField che si desidera controllare e quindi fare qualcosa come il seguente in una funzione controlTextDidChange: che viene richiamata su ogni carattere digitato. Non dimenticare di inizializzare self.lastValidTimestampCount in questo caso. Questa funzione utilizza RegExLite per verificare il valore, che può includere virgole.

// Make sure the user has typed a valid number so far. 
- (void)controlTextDidChange:(NSNotification *)obj 
{ 
    if (obj.object == self.timestampsCount) 
    { 
     NSString *countValue = timestampsCount.stringValue; 
     if (! [countValue isMatchedByRegex:@"^[\\d\\,]{1,6}$"]) 
     { 
      timestampsCount.stringValue = self.lastValidTimestampCount; 
      NSBeep(); 
     } 
     else 
      self.lastValidTimestampCount = timestampsCount.stringValue; 
    } 
} 
1

risposta del NPAssoc fatto aiutarmi e ho fatto una piccola modifica al codice che non ha utilizzato la funzione isMatchedByRegex.

// Make sure the user has typed a valid number so far. 
- (void)controlTextDidChange:(NSNotification *)obj 
{ 
    if (obj.object == self->number) 
    { 
     NSString *countValue = number.stringValue;   
     if ([countValue length] > 0) { 
      if ([[countValue substringFromIndex:[countValue length]-1] integerValue] > 0 || 
       [[countValue substringFromIndex:[countValue length]-1] isEqualToString:@"0"]) 
      { 
       self.lastNumber = number.stringValue; 
      } 
      else 
      { 
       number.stringValue = self.lastNumber; 
       NSBeep(); 
      } 
     } 
    } 
} 

PS: Utilizzare la [auto setIntValue: [sé intValue]] limita la lunghezza dell'input.

2

Ecco un'implementazione alternativa:

+ (BOOL)stringIsNumber:(NSString *)str { 
    BOOL valid; 
    double holder; 
    NSScanner *scan = [NSScanner scannerWithString: str]; 
    valid = [scan scanDouble:&holder] && [scan isAtEnd]; 
    return valid; 
} 

+ (NSString *)numericStringFromString:(NSString *)string { 
    NSString *digitsString = string; 
    if (![YOURCLASSNAME stringIsNumber:string]) { 
     NSUInteger length = [string length]; 
     if (length > 0) { 
      digitsString = [string substringToIndex:length - 1]; 
      if (![YOURCLASSNAME stringIsNumber:digitsString]) { 
       digitsString = [YOURCLASSNAME numericStringFromString:digitsString]; 
      } 
     } 
    } 
    return digitsString; 
} 

Poi nella mia classe Controller, implemento controlTextDidChange:

- (void)controlTextDidChange:(NSNotification *)obj { 
    NSString *digitsString = [YOURCLASSNAME numericStringFromString:self.currentCellView.textField.stringValue]; 
    if (digitsString) { 
    self.currentCellView.textField.stringValue = digitsString; 
    } else { 
    self.currentCellView.textField.stringValue = @""; 
    } 
} 

Il vantaggio di questo approccio è che se si incolla il testo nel campo di numero, questo rimuoverà tutti i caratteri non numerici dalla fine della stringa finché non rimarrai con un numero. Inoltre supporta una serie arbitrariamente lunga di cifre. Alcuni degli altri approcci non supportano l'inserimento di una serie di cifre che non possono essere contenute in un NSInteger.

So che questo approccio potrebbe certamente essere migliorato.

+0

cosa sono le utilità in questo ??? – VSN

+0

Fatto .... nel posto di Utilities abbiamo bisogno di scrivere il nostro nome di classe .. ha funzionato per me ... grazie. – VSN

+0

Siamo spiacenti, si Utilità è solo la classe che contiene il metodo numericStringFromString che è stato fornito nella risposta. –

3

Ecco i passaggi per creare la stessa:

Basta creare l'ANYCLASS (chiamato CAMPIONE) sottoclasse il NSNumberFormatter, e nel file .m scrivere il codice seguente ...

 (BOOL)isPartialStringValid:(NSString *)partialString newEditingString:(NSString **)newString errorDescription:(NSString **) error { 
    // Make sure we clear newString and error to ensure old values aren't being used 
    if (newString) { *newString = nil;} 
    if (error)  {*error = nil;} 

    static NSCharacterSet *nonDecimalCharacters = nil; 
    if (nonDecimalCharacters == nil) { 
     nonDecimalCharacters = [[NSCharacterSet decimalDigitCharacterSet] invertedSet] ; 
    } 

    if ([partialString length] == 0) { 
     return YES; // The empty string is okay (the user might just be deleting everything and starting over) 
    } else if ([partialString rangeOfCharacterFromSet:nonDecimalCharacters].location != NSNotFound) { 
     return NO; // Non-decimal characters aren't cool! 
    } 

    return YES; 
} 

Ora nella tua classe effettiva impostare il formattatore al vostro oggetto NSTextField in questo modo:

NSTextField *mySampleTxtFld; 

E per questo impostare il formatter:

SAMPLE* formatter=[[SAMPLE alloc]init]; // create SAMPLE FORMATTER OBJECT 

self.mySampleTxtFld.delegate=self; 
[self.mySampleTxtFld setFormatter:formatter]; 

Il gioco è fatto!

+0

Questa sembra una grande soluzione. –

+0

Grazie a @TapForms. – VSN

+0

Ottimo esempio: davvero utile – eww

Problemi correlati