2010-11-03 19 views
1

J'ai un code que je porte d'iOS 4 à iOS 3.2 pour un projet de démonstration sur un iPad. J'ai ce code:NSNumberFormatter iOS 3.2 Bug?

+(int) parseInt:(NSString *)str 
{ 
    NSNumberFormatter *nf = [[NSNumberFormatter alloc] init]; 
    [nf setAllowsFloats:NO]; 
    [nf setMaximum:[NSNumber numberWithInt:INT_MAX]]; 
    [nf setMinimum:[NSNumber numberWithInt:INT_MIN]]; 

    @try { 
     NSNumber *num = [nf numberFromString:str]; 
     if (!num) 
      @throw [DataParseException exceptionWithDescription:@"the data is not in the correct format."]; 

     return [num intValue]; 
    } 
    @finally { 
     [nf release]; 
    } 
} 

Cela fonctionne spendid sur iOS 4, jetant des exceptions quand une chaîne (comme une date, que je rencontre des problèmes avec): 1/1/2010

Pour une raison quelconque, num ISN 't nul, il a la valeur 1, tandis que sur iOS 4, il est nul comme prévu. J'utilisais initialement NSScanner parce qu'il était plus facile que NSNumberFormatter à utiliser, mais j'ai rencontré le même problème, il n'analyse pas toute la chaîne, seulement le premier nombre de la chaîne.

Y at-il quelque chose que je peux faire pour résoudre ce problème, ou dois-je créer manuellement un parseur int. Je préférerais ne pas utiliser une approche C-Based, mais si je dois, je le ferai.

EDIT: J'ai mis à jour mon code à ceci:

+(int) parseInt:(NSString *)str 
{ 
    NSNumberFormatter *nf = [[NSNumberFormatter alloc] init]; 
    [nf setAllowsFloats:NO]; 
    [nf setMaximum:[NSNumber numberWithInt:INT_MAX]]; 
    [nf setMinimum:[NSNumber numberWithInt:INT_MIN]]; 

    @try { 
     IF_IOS4_OR_GREATER 
     (
       NSNumber *num = [nf numberFromString:str]; 
      if (!num) 
       @throw [DataParseException exceptionWithDescription:@"the data is not in the correct format."]; 

      return [num intValue]; 
     ) 
     else { 
      NSNumber *num = nil; 
      NSRange range = NSMakeRange(0, str.length); 
      NSError *err = nil; 
      [nf getObjectValue:&num forString:str range:&range error:&err]; 
      if (err) 
       @throw [DataParseException exceptionWithDescription:[err description]]; 
      if (range.length != [str length]) 
       @throw [DataParseException exceptionWithDescription:@"Not all of the number is a string!"]; 
      if (!num) 
       @throw [DataParseException exceptionWithDescription:@"the data is not in the correct format."]; 

      return [num intValue]; 
     } 
    } 
    @finally { 
     [nf release]; 
    } 
} 

et je reçois un signal EXC_BAD_ACCESS lorsque je tente d'analyser la chaîne 1/1/2001. Des idées? (iOS 4 ou supérieur est défini ici: http://cocoawithlove.com/2010/07/tips-tricks-for-conditional-ios3-ios32.html)

J'ai une nouvelle erreur: quand je parse le nombre, il est exact (exact comme il a plusieurs chiffres après la virgule lors de l'utilisation même code pour les flotteurs) plus .... comment puis-je résoudre ce problème ?? (Je pourrais juste utiliser la réponse de @ joshpaul ...)

+0

Vous ne devriez vraiment pas utiliser une exception pour cela. Les exceptions dans obj-c sont destinées à signaler les erreurs du programmeur. Les erreurs de données, comme celle-ci, doivent utiliser une API basée sur NSError *. –

+0

Désolé, mon patron et moi avons un problème avec 'nils' juste en cours d'exécution dans le code ... –

+0

@Kevin Ballard: Avec cette API, il n'y a aucun moyen d'indiquer une valeur d'erreur puisque tout int est valide. – JeremyP

Répondre

1

Donc le [str intValue] de base ne fonctionne pas? Nor, [scanner scanInt:&int]?

Qu'en est-il en utilisant NSCharacterSet, à savoir:

NSString *test = [str stringByTrimmingCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]]; 
if ([test length]) @throw ...; 
return [str intValue]; 
+0

Une solution intéressante .... Je ne sais pas si cela est pratique pour moi .. Je vais essayer ce que @JeremyP a écrit et ensuite regardera à nouveau votre réponse –

4

Je ne pouvais pas trouver quelque chose de spécifique à iOS mais le data formatting guide a ce paragraphe intéressant:

Note: Prior to Mac OS v10.6, the implementation of getObjectValue:forString:errorDescription: would return YES and an object value even if only part of the string could be parsed. This is problematic because you cannot be sure what portion of the string was parsed. For applications linked on or after Mac OS v10.6, this method instead returns an error if part of the string cannot be parsed. You can use getObjectValue:forString:range:error: to get the old behavior; this method returns the range of the substring that was successfully parsed.

Je ne serais pas du tout surpris si numberFromString: a été implémenté en termes de la méthode ci-dessus et l'iOS 3.2 NSNumberFormatter est basé sur 10.5 alors que la version iOS 4 est 10.6.

Juste à mon avis.

Si vous passez 1/1/2010 sur iOS 3.2, le 1 sera analysé et le reste ignoré. Vous pourriez tester l'hypothèse en voyant si vous obtenez 2 lorsque vous passez le 2/1/2010.

Le travail semble être d'utiliser getObjectValue:forString:range:error:.

+0

Pourquoi ne peut-il pas être juste un simple int.Parse() 'appel :) –

+0

@Richard J. Ross III: bien, vous pouvez regarder' NSDecimalNumber decimalNumberWithString: ' – JeremyP