NSFormatter
chaps31
Membre
:brule: 3 heures... 3h... que je m'arrache les cheveux sur cette classe, que je lis la doc succinte d'apple et que... je ne comprends pas grand chose visiblement car rien ne marche... Je veux faire un truc hyper simple et je ne comprends pas qu'avec cocoa cela soit si compliqué mais passons.
J'ai des NSTextField dans mon interface 2 doivent être en majuscule, 2 en nom propre (capitalized) et 1 avec numéro de téléphone (XX.XX.XX.XX.XX).
J'essai majuscule, je crée une sous-classe NSFormatter dans x-code que j'instancie dasn IB et relie avec un NSTextField: formatter connect. OK.
Bon je dois implémenter 3 méthodes obligatoirement :
stringForObjectValue:
getObjectValue:forString:errorDescription:
attributedStringForObjectValue:withDefaultAttributes:
C'est parti :
[tt](NSString *)stringForObjectValue:(id)anObject
{
return [[anObject stringValue] uppercaseString];
}
(BOOL)getObjectValue:forString:errorDescription:
{
//Juste pour vérifier que l'on retourne ce qui faut ?
return YES;
}
(attributedString *)attributedStringForObjectValue:withDefaultAttributes:
{
//Retour d'un attributedString , pour quoi faire dasn mon cas ??
return nil;
}
[/tt]
Je sens bien que je n'ai pas compris grand chose... :)beta: Et ça bug merveilleusement :crackboom:- , je ne trouve rien de probant sur le net... Quelques minutes à m'offrir ?? milles merci...
J'ai des NSTextField dans mon interface 2 doivent être en majuscule, 2 en nom propre (capitalized) et 1 avec numéro de téléphone (XX.XX.XX.XX.XX).
J'essai majuscule, je crée une sous-classe NSFormatter dans x-code que j'instancie dasn IB et relie avec un NSTextField: formatter connect. OK.
Bon je dois implémenter 3 méthodes obligatoirement :
stringForObjectValue:
getObjectValue:forString:errorDescription:
attributedStringForObjectValue:withDefaultAttributes:
C'est parti :
[tt](NSString *)stringForObjectValue:(id)anObject
{
return [[anObject stringValue] uppercaseString];
}
(BOOL)getObjectValue:forString:errorDescription:
{
//Juste pour vérifier que l'on retourne ce qui faut ?
return YES;
}
(attributedString *)attributedStringForObjectValue:withDefaultAttributes:
{
//Retour d'un attributedString , pour quoi faire dasn mon cas ??
return nil;
}
[/tt]
Je sens bien que je n'ai pas compris grand chose... :)beta: Et ça bug merveilleusement :crackboom:- , je ne trouve rien de probant sur le net... Quelques minutes à m'offrir ?? milles merci...
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Et là évidemment il s'agit du paramètre [tt]getObjectValue:(id *)anObject[/tt] : donc il faut que ta méthode retourne l'objet, correspondant à la chaà®ne passée en 2e paramètre, dans ce paramètre anObject. Et la valeur de retour c'est juste pour indiquer si la conversion a réussi ou si elle est impossible (impossible d'interpréter la chaà®ne pour construire un objet)
Je ne vois pas ce qui te bloque : il y a même des exemples dans la doc Apple à ce propos ! getObjectValue:forString:errorDescription:
Ce qui donne, en l'occurence puisque c'est déjà une chaà®ne, ben directement la chaà®ne en fait
Et pour le coup du attributedString, c'est aussi expliqué pourquoi il faut le réimplémenter (c'est pour les cas où tu veux afficher du texte dans un format ou une couleur différente selon l'objet ou sa valeur, genre des nombres négatifs en rouge par ex....) et c'est même expliqué comment il faut la coder : donc :
Enfin je sais pas j'ai jamais codé de custom NSFormatter mais bon c'est ce que je comprends de la doc en tout cas
Vraiment il y avait un gros bordel et maintenant c'est rangé impec, vraiment merci. Allez je retourne au code j'ai 10 min.
:adios!: :adios!:
- (NSAttributedString *)attributedStringForObjectValue:(id)anObject withDefaultAttributes:(NSDictionary *)attributes
{
NSAttributedString* retVal;
NSString* str = [self stringForObjectValue:anObject];
[retVal initWithString:str attributes:attributes];
return retVal;
}
- (NSString *)stringForObjectValue:(id)anObject
{
return [anObject uppercaseString];
}
- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error
{
*anObject = string;
return YES;
}
@end
J'ai corrigé un truc (anobject est un string donc mon stringValue...hum) ça bug toujours à cause de retVal, le debugger me dit "out of scope", une idée ?
NB :AttributedString ne répond pas à alloc d'où la modif.
Tout NSObject répond à alloc
Il n'y a que la classe qui puisse allouer, puisque l'instance n'existe qu'après allocation.
Du coup il te disait que l'objet "retVal" (de type NSAttributedString bien que pas encore alloué) ne répondait pas à -alloc (et c'est vrai) : alloc est une méthode de classe comme l'a indiqué Philippe49 (d'où le "+alloc", le "+" mentionnant une méthode de classe), on demande à la classe NSAttributedString d'allouer une variable de ce type, on demande pas à la variable retVal qui d'ailleurs n'existe pas encore vraiment. My mistake.
De plus, j'avais oublié le "return YES" dans le getObjectValue:... (mais tu l'as rajouté tout seul)
Du coup j'ai édité mon post plus haut pour corriger ces deux étourderies (j'ai carrément tout condensé sur une ligne, direct le return au lieu de la variable retVal intermédiaire), et ça devrait être bon
Merci à vous 2 du temps passé à me répondre (encore et encore), ça fonctionne impec, trop heureux, promis je vais progresser
Une remarque étrange j'ai lié mon formatter à 2 champs un nssearchfield et un nstextfield. Pour le premier nickel quand je tape, les lettres sont en majuscules, par contre pour le deuxième la casse est celle de la frappe... Et le formatter est appliqué uniquement quand je déselectionne le nstextfield, là tout passe en majuscule c'est bizarre non ?
Je pensais qu'un formatter formattait le champs dès que l'on tapait qque chose pas uniquement après validation...
Tu as bien raison ...
Dans le panel Attributes --> Control --> State --> Continuous
Ce n'est pas dramatique, mais c'est sûr c'est mieux quand à chaque frappe le format est pris en compte (depuis j'ai aussi mis en place un format pour les numéro de téléphone).
Prendre ce qui correspond à l'envoi au fur et à mesure, et non après Enter
(Il n'y a que quand j'utilise les bindings que j'ai l'option dans le panel du binding en question "Continuously Updates Value", mais bon)
Peut-être peux-tu t'en sortir en implémentant en plus les méthodes du NSFormatter dédiées à l'édition, et non pas que à l'affichage ?
Enter Only cela doit être une autre option
Enter only --> on appuie sur la touche Enter (non, sans blague ?)
End editing --> on a fini l'édition, soit par appui sur la touche enter, soit par l'appui sur la touche Tab pour passer à un autre champ, ou par clic autre part (un bouton, le fond de la fenêtre, etc) qui a fait finir l'édition... non ?
Voilà ce qu'il y a dans Leopard, il faudrait essayer [myTextField setContinous:YES];
NSControl
setContinuous:
Sets whether the receiver's cell sends its action message continuously to its target during mouse tracking.
J'avais essayé en mettant ça dans awakefromnib, sans succès.
Je n'avais pas fait plus attention que ça aux méthodes spéciales numéro de tel... faut que je regarde ça de plus près d'autant plus qu'avec ma technique j'ai un pb pour les nssearchfield, un qui utilise le formatter majuscule pas de pb, mais un qui utilise le format téléphone, celui-là une fois relié au formatter je ne peux plus rien taper... (il y a un lien vers un IBAction qui fait travailler ma tableview) Donc je vais regarder les 2 méthodes qui m'ont l'air encore un tantinet hardue à comprendre, enfin pour moi :P
- (BOOL)isPartialStringValid:(NSString *)partialString newEditingString:(NSString **)newString errorDescription:(NSString **)error
{
*newString=[partialString uppercaseString];
return NO;
}
En essayant, cela m'a rappelé qu'on pouvait mettre le CustomFormatter dans le MainMenu.nib, et le connecter dans IB.
Les nssearchfield, ne sachant pas trop comment ils fonctionnent j'ai créé un IBAction qui fait la recherche puis un scroll sur la tableview relié au nssearchfield ce qui marche impec (en notant que cela ne marche pas avec un nstextfield, la frappe pour ce type de champs ne déclenche pas l'IBAction cela ne semble fonctionner qu'avec les nssearchfield).
Mais dans les attributs des nssearchfield il y a des options pour les recherches que je n'utilise pas, du coup je me demande si je prend les nssearchfield par le bon avec mes IBAction.
NB : juste une question c'est quoi cette notation double étoile (NSString **) ?
NSString * avec une étoile = l'adresse où se trouve les données de la NSString
NSString ** avec deux étoiles = l'adresse de l'adresse où se trouve les données de la NSString
(Pour un 4 étoiles, c'est plus cher ... )
#import <Foundation/Foundation.h>
void changeMyString(NSString ** stringptr)
{
*stringptr=[NSString stringWithString:@n'importe ou];
}
int main(int argc, char**argv){
NSAutoreleasePool * pool=[[NSAutoreleasePool alloc] init];
NSString * aString=@n'importe quoi;
changeMyString(& aString);
NSLog(aString);
[pool release];
return 0;
}
Execution
%gcc pgm.m -o pgm -framework Foundation
% pgm
2008-04-13 14:59:06.515 pgm[2493:10b] n'importe ou
%
[tt]#import "majuscule.h"
@implementation majuscule
- (NSAttributedString *)attributedStringForObjectValue:(id)anObject withDefaultAttributes:(NSDictionary *)attributes
{
NSString* str = [self stringForObjectValue:anObject];
return [[[NSAttributedString alloc] initWithString:str attributes:attributes] autorelease];
}
- (NSString *)stringForObjectValue:(id)anObject
{
return [NSString stringWithFormat:@%@",anObject];
}
- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error
{
*anObject = string;
return YES;
}
- (BOOL)isPartialStringValid:(NSString *)partialString newEditingString:(NSString **)newString errorDescription:(NSString **)error
{
*newString=[partialString uppercaseString];
return NO;
}
@end[/tt]
NB : pour le formatter générique je ne vois pas trop comment en liant à mes champs dans IB il peut savoir que ce champs c'est un nom propre celui-là en majuscule...