# [Cocoa] sous classe de NSNumberFormatter



## .mok. (30 Avril 2007)

Salut tout le monde 

Voilà, j'ai un léger problème sous Cocoa, que je commence à apprendre petit à petit... J'ai besoin de formatter un champ pour une ip, donc pour faire simple j'ai divisé mon ip en 4 champs NSTextfield : XXX XXX XXX XXX . Je récupérerai ensuite la valeur et la formatterai de façon adéquate.

Pour éviter que l'utilisateur ne rentre des caractères autres que des numéros, j'ai sous classé un NSNumberFormatter que j'ai appellé ipAddress . J'ai donc utilisé une méthode isPartialStringValid pour empécher la saisie de caractères alphabétiques et de symboles, j'ai ensuite lié mon formatteur a mon TextField. Tout ça marche très bien. Seuls les chiffres sont pris en compte.

Le problème c'est qu'a chaque fois que je passe à un autre champ en appuyant sur tab par exemple, j'ai un .00 qui apparait derriere mes 3 chiffres !

Je pense que je dois réécrire certaines méthodes qui sont héritées de NSNumberFormatter, mais j'ai pas mal cherché et je ne trouve pas ! Il ya surement des choses que je n'ai pas comprises donc soyez indulgents :love: 

Merci pour votre aide !


----------



## claw59 (30 Avril 2007)

A mon avis, il serait plus judicieux d'utiliser 1 seul instance 'NSTextField' en cohésion avec un 'NSFormatter' :

exemple de zone formattée : "####.####.####.####"

les caractères # représente les 'char' éditable grâce à NSTextField, il faudrait configurer NSTextField pour qu'il n'accepte en entrée QUE des chiffres numériques !


----------



## .mok. (30 Avril 2007)

je pourrais essayer ça comme ça, mais quelle methode sert à formatter l'affichage exactement ?


----------



## .mok. (2 Mai 2007)

je ne trouve pas quelles méthodes servent à définir l'affichage :

il me faudrait simplement ### : 3 chiffres, pas de virgule ni rien...


----------



## claw59 (2 Mai 2007)

je ne sais pas exactement quelle m&#233;thode il faut choisir mais :

- (NSString *)editingStringForObjectValueid)anObject 

celle-ci est une m&#233;thode int&#233;ressante, car une fois qu'elle est surcharg&#233;e, si ton objet d&#233;riv&#233;e de NSTextField contient un objet AdresseReseau

@interface AdresseReseau
{
short int left;
short int middle;
short int right;
}

en passant AdresseReseau en argument, tu pourrais le mapper en une chaine NSString

j'ai trouv&#233; un lien qui te fournira un code beaucoup plus propre pour apprendre &#224; utiliser NSFormatter et cela se trouve &#224; cet endroit


----------



## .mok. (2 Mai 2007)

Merci beaucoup Claw59 

Je venais juste de tomber sur cette page quelques minutes avant de voir ta réponse, comme quoi 

J'ai réussi à enlever les .00 qui m'énervaient, je vais bien regarder tout ça en détail  
Merci encore:love:


----------



## .mok. (2 Mai 2007)

Bon j'ai regardé un peu editingStringForObjectValue, et à vrai dire, je ne vois pas trop à quoi cela correspond, 



> When implementing a subclass, override this method only when the string that users see and the string that they edit are different.



Ceci dit, j'ai réussi à faire quelques petites choses : 
- minimum 0 maximum 255 (ne valide pas sinon)
- enlever le .00 qui se rajoutait automatiquement
- interdire l'utilisation de lettres à la frappe

Je pense qu'une dernière methode qui permettrait de rentrer au maximum 3 chiffres serait la bienvenue, j'ai trouvé la méthode maximumIntegerDigits mais elle n'a pas l'air de marcher, ou je m'en sert très mal ? (il suffit de retourner un unsigned int égal à trois non?)


----------



## p4bl0 (2 Mai 2007)

.mok. a dit:


> Bon j'ai regardé un peu editingStringForObjectValue, et à vrai dire, je ne vois pas trop à quoi cela correspond,
> 
> 
> 
> ...


Mais si tu as d&#233;j&#224; "minimum 0 maximum 255 (ne valide pas sinon)" alors tu n'as pas besoin de limiter &#224; trois chiffres vu qu'avec plus de trois chiffres c'est forc&#233;ment superieur &#224; 255 non ?

Il suffit de supprimmer automatiquement les z&#233;ro de gauche si il y en a et qu'il y a plus qu'un chiffre (vu que la seule possibilit&#233; de nombre &#224; plus de 3 chiffres mais pas superieur &#224; 255 c'est 0123 par exemple ou 0002 etc...)


Mais peut-&#234;tre que je suis compl&#232;tement &#224; l'ouest


----------



## .mok. (2 Mai 2007)

Salut p4bl0,

oui en effet ça ne sert pas a grand chose de limiter le nombre de caractères à trois, mais personnellement je trouve ça un peu plus propre (vu que ce sont des petits textfields, si on rentre + de 3 caractères y'a des chiffres qu'on ne voit plus, et c'est laid )

pour l'histoire du zéro, apparement c'est géré automatiquement (disons que quand je rentre 0123 par exemple, ça écrit 123 dans le textfield)


----------



## .mok. (2 Mai 2007)

En fait j'ai r&#233;ussi &#224; bloquer au dessus de 3 chiffres en rajoutant deux lignes de code sur la m&#233;thode isPartialStringValid 

EDIT : bah ouais mais apr&#232;s je  peux plus supprimer ce que j'ai rentr&#233;


----------



## p4bl0 (2 Mai 2007)

.mok. a dit:


> Salut p4bl0,
> 
> oui en effet ça ne sert pas a grand chose de limiter le nombre de caractères à trois, mais personnellement je trouve ça un peu plus propre (vu que ce sont des petits textfields, si on rentre + de 3 caractères y'a des chiffres qu'on ne voit plus, et c'est laid )
> 
> pour l'histoire du zéro, apparement c'est géré automatiquement (disons que quand je rentre 0123 par exemple, ça écrit 123 dans le textfield)


Ok, mais je comprend toujours pas comment on peut entrer un nombre &#224; 4 chiffres si le nombre doit &#234;tre "minimum 0 maximum 255 (ne valide pas sinon)" et que "l'histoire du z&#233;ro, apparement c'est g&#233;r&#233; automatiquement" 


M'enfin c'est pas tr&#232;s important que je comprenne pas, j'esp&#232;re que tu r&#233;ussira &#224; r&#233;soudre ton probl&#232;me


----------



## .mok. (2 Mai 2007)

Ben en fait, quand on met un maximum à 255, le champs peut toujours afficher des valeurs au dessus de 255 mais ne peut pas les valider en appuyant sur tab pour passer au champs suivant par exemple.

Ce qui serait super comme validation c'est de regarder si le premier chiffre entré est entre 0 et 2, le second entre 0 et 5, le troisieme idem, mais ça ne marche pas comme ça. En fait faudrait le faire je pense avec isPartialStringValid, mais ça me parait beaucoup trop compliqué pour moi :'(


----------



## p4bl0 (2 Mai 2007)

Et juste comme &#231;a : http://www.google.com/search?hl=en&q=Cocoa+textfield+ip+address

m'a tr&#232;s vite amen&#233; (deux clic depuis la recherche) &#224; &#231;a : http://s.sudre.free.fr/Software/DevPotPourri.html (cherche WBIPv4Control dans la page )


----------



## p4bl0 (2 Mai 2007)

.mok. a dit:


> Ben en fait, quand on met un maximum à 255, le champs peut toujours afficher des valeurs au dessus de 255 mais ne peut pas les valider en appuyant sur tab pour passer au champs suivant par exemple.
> 
> Ce qui serait super comme validation c'est de regarder si le premier chiffre entré est entre 0 et 2, le second entre 0 et 5, le troisieme idem, mais ça ne marche pas comme ça. En fait faudrait le faire je pense avec isPartialStringValid, mais ça me parait beaucoup trop compliqué pour moi :'(


Ah non surtout pas le second entre 0 et 5 !! 187 c'est valide par exemple


----------



## p4bl0 (2 Mai 2007)

Tiens la recherche que je t'ai fil&#233; tout &#224; l'heure m'a aussi donn&#233; &#231;a : http://www.developpez.net/forums/showthread.php?p=2012062 ^^


----------



## .mok. (2 Mai 2007)

ah oui je suis con pour le 0 et le 5 ^^ il se fait tard 

je vais regarder ce que tu m'as donn&#233; 

edit :  oui oui c'est moi


----------



## p4bl0 (2 Mai 2007)

.mok. a dit:


> ah oui je suis con pour le 0 et le 5 ^^ il se fait tard
> 
> je vais regarder ce que tu m'as donn&#233;
> 
> edit :  oui oui c'est moi


Le WBIPv4Control m'a l'air d'&#234;tre tout &#224; fait ce que tu cherche :


----------



## .mok. (2 Mai 2007)

Tu as trouvé ça où ?

En fait je viens justement de finir ma classe IpV4 je crois  J'ai trouvé ce qui foirait, maintenant j'ai réussi a quasiment bloquer toutes les erreurs possibles...


----------



## p4bl0 (2 Mai 2007)

j'ai trouv&#233; &#231;a l&#224;.





p4bl0 a dit:


> http://s.sudre.free.fr/Software/DevPotPourri.html (cherche WBIPv4Control dans la page )


----------



## claw59 (3 Mai 2007)

on pourrai aussi imaginer le fonctionnement d'un objet

@interface AdressReseau
{

struct AdrReseau adrResau;

}

gérant cette structure de manière dynamique:

typedef union AdrReseau
{

   typedef struct Ipv4 {....}

   typedef struct Ipv6 {....}

}


----------



## tatouille (4 Mai 2007)

claw59 a dit:


> on pourrai aussi imaginer le fonctionnement d'un objet
> 
> @interface AdressReseau
> {
> ...


il y a deja des trucs tout fait ...


----------



## p4bl0 (4 Mai 2007)

tatouille a dit:


> il y a deja des trucs tout fait ...


Cf le lien que j'ai donn&#233; deux fois :rateau:


----------



## .mok. (5 Mai 2007)

re salut 

d'abord merci pour le lien, je m'embetterai moins la prochaine fois  j'ai quand même gardé mon code, on doit faire tout nous même pour notre projet... 

en fait j'ai un peu avancé, et là je cherche comment bloquer le nombre de caractères dans un champs NSTextView, apparement on peut pas lui coller un NSFormatter (dont je me sert pour des NSTextFields). je ne sais pas trop comment faire :'(


----------



## p4bl0 (5 Mai 2007)

_&#171; No problem should ever have to be solved twice. &#187;_


----------



## Tarul (5 Mai 2007)

.mok. a dit:


> re salut
> 
> d'abord merci pour le lien, je m'embetterai moins la prochaine fois  j'ai quand même gardé mon code, on doit faire tout nous même pour notre projet...
> 
> en fait j'ai un peu avancé, et là je cherche comment bloquer le nombre de caractères dans un champs NSTextView, apparement on peut pas lui coller un NSFormatter (dont je me sert pour des NSTextFields). je ne sais pas trop comment faire :'(



l'une des solutions serait de sous-classer ton NSTextView pour intégrer cette notion de limitation de taille.

Sinon a chaque changement de valeur de ton textview, tu vérifie la taille de ta chaîne et tu fais le traitement limitatif, cela t'évite de sous-classer. Mais c'est sans doute la méthode la moins propre je pense.


----------



## .mok. (6 Mai 2007)

Salut 

Alors j'ai regardé un peu comment sous classer NSTextView, mais je ne trouve pas vraiment de méthode équivalente à isPartialStringValid qui me permettait de compter les caractères, mais je vais regarder ça plus en détail.

Sinon j'avais une autre question, à propos des bindings, j'ai réussi à faire des trucs sympas assez rapidement avec, mais je bloque sur un truc un peu plus compliqué :

j'aimerai activer un champs seulement lorsque l'utilisateur a tappé dans un autre, mais je n'y arrive pas du tout avec "l'inspecteur", comment faire ?


----------



## Tarul (7 Mai 2007)

.mok. a dit:


> Salut
> 
> Alors j'ai regardé un peu comment sous classer NSTextView, mais je ne trouve pas vraiment de méthode équivalente à isPartialStringValid qui me permettait de compter les caractères, mais je vais regarder ça plus en détail.
> 
> ...



On va sûrement me reprendre, mais le binding ne semble pas du tout approprié pour ta dernière demande. 
Je rajouterait plutôt le controllerApp en client d'une notification du champs text qui t'intéresse. et dans la méthode de réception de la notification tu testes la nouvelle valeur et en fonction du résultat tu actives-désactives ton champs.

voici un lien vers un tuto sur les notifications : http://www.projectomega.org/article.php?lg=fr&php=tuts_objc5&p=1


----------



## .mok. (11 Mai 2007)

salut 

finalement j'ai laissé tombé pour l'activation des champs, ça me paraissait trop compliqué, et en même temps, je me suis apperçu de quelquechose :

J'ai un bouton radio qui me sert à activer/désactiver des champs grâce aux bindings. Ces champs sont associés a ma classe Ip qui descend d'un NSNumberFormatter. Et bien figurez vous que le maximum de 255 n'est plus pris en compte sur les champs bindés !

Ceux qui n'ont aucun bindings envoient un beep lorsque je rentre par exemple 257 et que j'appuie sur la touche tab, ceux qui sont bindés prennent 257 sans se poser de question, pourtant les autres méthodes de ma classe Ip sont prises en compte... 

quelqu'un aurait il une idée ??


----------



## Trax (12 Mai 2007)

Pour l'interdiction "&#224; la vol&#233;e", je me dis que d'overrider keyDown fera la job. Juste &#224; capturer la cl&#233; press&#233;e et v&#233;rifier si le caract&#232;re correspond &#224; ce que tu veux...

- (void)keyDownNSEvent *)zeEvent
{
    if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:[[zeEvent characters] characterAtIndex:0]])
    [super keyDown:zeEvent];
else
    NSBeep();
}

&#199;a r&#232;gle le probl&#232;me des caract&#232;res non-num&#233;riques, mais pas le reste. Mais cette ligne pourrait aussi &#234;tre int&#233;gr&#233;e facilement &#224; isPartialString...


----------



## .mok. (13 Mai 2007)

Salut 

-> Trax : merci, mais en fait le problème de l'interdiction à la volée est déjà réglé ! J'ai effectivement créé ma classe avec la méthode isPartialStringValid et ça marche très bien.


En fait actuellement j'essaie d'inclure une progress bar qui avancerait toutes les 2 secondes de 0 à 100. Je n'arrive ABSOLUMENT pas à la faire avancer, et pourtant j'ai regardé je ne sais combien de tutos sur le net, donc un truc doit vraiment m'échapper... 
Si quelqu'un pouvait m'aider ça serait top !
:love:


----------



## Tarul (14 Mai 2007)

.mok. a dit:


> Salut
> 
> -> Trax : merci, mais en fait le problème de l'interdiction à la volée est déjà réglé ! J'ai effectivement créé ma classe avec la méthode isPartialStringValid et ça marche très bien.
> 
> ...



il te faut faire un NSTimer, mettre ton controller ou ta classe en deleguer du Timer pour sa notification de mise à jour. Il te reste ensuite a implémenter la méthode de mise à jour de ton progresssbar.

Je te posterait si tu veux un exemple plus tard.


----------



## Trax (14 Mai 2007)

Je pense que le mot-clé important est : display...
Si tu reste coincé dans une méthode (probablement une boucle assez longue), tu peux forcer le contrôle à se redessiner immédiatement...

...
[barreProgres incrementBy:2.0];
[barreProgres display];
...


----------



## .mok. (16 Mai 2007)

Salut 

ben effectivement ya pas moyen de la faire bouger donc je dois reellement avoir un problème, je vous file mon code parceque là  

j'ai réussi a faire bouger un level indicator de la même façon... 

                sleep=sleep+2;    
                    [TRANSMISSION_progressBar setMaxValue:sleep];    
                    [TRANSMISSION_progressBar setIndeterminate:YES];
                    [TRANSMISSION_progressBar setUsesThreadedAnimation:YES];
                    int cpt=0;
                    for(cpt; cpt<=sleep;cpt++)
                    {
                        system("sleep 1");
                        [TRANSMISSION_progressBar setIntValue:cpt];
                        [TRANSMISSION_progressBar displayIfNeeded];
                    }


je comprend pas trop


----------



## Trax (16 Mai 2007)

Hmm, bon, pour ce qui est de _display_ vs _displayIfNeeded_, j'ai fait un test et il n'y a pas de diff&#233;rence. Le probl&#232;me, c'est que tu met ta barre en _indeterminate_ :

[TRANSMISSION_progressBar setIndeterminate:YES];

Met "NO" &#224; la place...

En mettant "YES", c'est suppos&#233; te donner le poteau de barbier (qui peut &#234;tre anim&#233; lui aussi, mais il ne "progresse" pas, il fait juste tourner &#224; l'infini)...


----------



## .mok. (16 Mai 2007)

Salut 

Merci pour ta réponse, ça a effectivement résolu le problème  

Maintenant j'en ai un autre :love:

En fait la progress bar devrait refléter l'avancement de la transmission de données de notre programme mais il y a un léger problème : dans le code, je lance la progress bar et je lance ma transmission de données l'une après l'autre. Evidemment, l'un se lance une fois que l'autre a terminé. Il faudrait que les deux se lancent en parallèle mais je n'ai absolument aucune idée de comment réaliser cela, je pense qu'il faudrait surement utiliser des threads mais voilà comme vous l'aurez remarqué mon niveau de cocoa est euh 

NSTask ? NSThread ? J'ai commencé a chercher mais sur la méthode pour implémenter ça en parallèle...


----------



## .mok. (16 Mai 2007)

Salut, finalement on s'est débrouillé autrement, un progressbar indeterminate qu'on arrete à la fin du shell script qui nous bloque, ça marche très bien comme ça !


----------

