TextField & ImageView + Threads

05:21 modifié dans API AppKit #1
Bonsoir,

J'ai remarqué que pile dans les 2 méthodes thread que j'appelle, des fois le textField ne se remplie pas et l'imageView m'affiche que l'icone "loadingIcon" (qui est blanche) alors qu'elle devrait en afficher une autre.
Voici le code :
<br />- (void)updateFieldsWithFreeware:(NSDictionary *)freeware<br />{<br />&nbsp; &nbsp; &nbsp; [usersMarkField setStringValue:NSLocalizedString(@&quot;Loading...&quot;,nil)];<br />&nbsp; &nbsp; &nbsp; [NSThread detachNewThreadSelector:@selector(showUserMark:) toTarget:self withObject:freeware];<br />	[NSThread detachNewThreadSelector:@selector(loadIcon:) toTarget:self withObject:freeware];<br />}<br /><br />- (void)loadIcon:(id)freeware<br />{<br />	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];<br />	NSImage*	_image;<br />	NSURL*	_url;<br />	<br />	[iconPI startAnimation:nil];<br />	_image = [NSImage imageNamed:@&quot;loadingIcon&quot;];<br />	[iconView setImage:_image];<br />	<br />	_image = nil;<br />	_url = [NSURL URLWithString:[NSString stringWithFormat:@&quot;http://www.eagle-of-liberty.com/~ifreete/%@&quot;, <br />																					[freeware objectForKey:@&quot;iconURL&quot;]]];<br />	_image = [[NSImage alloc] initWithContentsOfURL:_url];<br />	<br />	if(!_image){<br />		_image = [NSImage imageNamed:@&quot;error&quot;];<br />		[iconView setImage:_image];<br />	}else{<br />		[iconView setImage:_image];<br />		[_image release];<br />	}<br />	[iconPI stopAnimation:nil];<br />	<br />	[pool release];<br />}<br /><br />- (void)showUserMark:(id)freeware<br />{<br />	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];<br />	// ONLINE MARK<br />	NSString*	_userMarkString;<br />	NSString*	_URLString;<br />	<br />	_URLString = [[NSString stringWithFormat:@&quot;%@%@%@&quot;, MEDIUMMARKURL, [freeware objectForKey:@&quot;name&quot;], MEDIUMMARKURLEND] stringByAddingPercentEscapesUsingEncoding:NSISOLatin1StringEncoding];<br />	<br />	if([NSString instancesRespondToSelector:@selector(initWithContentsOfURL:encoding:error:)])<br />		_userMarkString = [[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:_URLString] encoding:NSUTF8StringEncoding error:nil];<br />	else<br />		_userMarkString = [[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:_URLString]];<br />		<br />	if(![_userMarkString isEqual:@&quot;&quot;])<br />		[usersMarkField setStringValue:[tableView checkMark:_userMarkString forImage:NO]];<br />	else<br />		[usersMarkField setStringValue:[tableView checkMark:nil forImage:NO]];<br />	[pool release];<br />}<br />


Pour le textField, il garde parfois le "Loading..." que j'envoie avant d'appeler le thread.
HuHuHu ?  :why?:

Merci,
Louka

Réponses

  • 05:21 modifié #2
    Déjà  première chose (j'ai pas lu ton code, trop long), tout ce qui concerne l'UI (dont les champs textes donc) n'est pas thread-safe. Donc tu ne peux pas utiliser un outlet dans une méthode que tu "détaches".

    Le truc est donc d'indiquer le changement à  faire dans le threadDictionary, d'enregistrer ton controlleur pour qu'il observe les notfs de fins de thread et de faire les changements à  la réception de la notif (et pas depuis le thread). La notif te permettra de récupérer le thread et donc son dictionnaire associé.
  • 05:21 modifié #3
    N'est-il pas plus simple (et possible?) de faire ça dans la notification d'exit du thread ?
    <br />- (void)threadWillExit:(NSNotification*)n<br />{<br />&nbsp; &nbsp;  [textField setString:_myString];<br />}
    


    Sinon, merci pour cette indication, Renaud
  • mars 2006 modifié #4
    et _myString tu le changes comment? depuis la méthode détachée? A éviter car il vaut mieux considérer que rien n'est thread-safe (à  part bien entendu ce que tu fais spécialement dans ce but et le dico de la thread). Surtout que dans ton cas, n'oublie pas que tu n'as qu'un seul champ texte et plusieurs peuvent avoir lieu en meme temps (et arriver dans un ordre différent, car les délais ne sont pas forcément identiques d'un moment à  l'autre).

    Sinon oui, le changement du champ texte se fait à  la réception de la notif, mais sur base du contenu du dico.
  • 05:21 modifié #5
    Ok donc dans une méthode thread je récupère ce que je veux, je le met dans le threadDictionary et à  la notification exit je récupère ce que j'ai introduit dans ce threadDictionary (le NSString par exemple) et je complète mon textField avec ce NSString

    Tout bon ?
  • 05:21 modifié #6
    Oui. Avec une vérification pour s'assurer que la notif reçue correspondent bien à  ce qui doit etre affiché (imagine que l'utilisateur choisit un freeware - la requete est envoyée, mais pr une raison X ou Y le résultat n'arrive pas tt de suite, l'utilisateur change de freeware, le fichier arriver et pouf l'UI est mise à  jour. Le résultat affiché ne correspondra donc pas à  la sélection en cours).
  • 05:21 modifié #7
    nickel
Connectez-vous ou Inscrivez-vous pour répondre.