2010-09-29 3 views
1

Im ayant quelques difficultés à faire passer un objet NSNumber à différents threads. J'appelle une fonction sur viewDidload qui charge certains objets à partir des données de base en tant que processus d'arrière-plan. qui appelle une autre fonction qui boucle à travers les objets chargés pour voir si des images associées sont déjà téléchargées. si ce n'est pas le cas, téléchargez les images de manière asynchrone et enregistrez-les localement. La chose est que je dois effectuer startDownloadFor: atIndex: sur le thread principal. Mais l'application se bloque à cause de l'objet NSNumber qui est passé. voici le code ..Iphone: objets Passing et les fils multiples

- (void)viewDidLoad { 
    ... 
    ... 
    [self performSelectorInBackground:@selector(loadImages) withObject:nil]; 
} 

-(void)loadImages{ 
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
... 
     ... 
[self fillInImages]; 
[pool release]; 
} 

-(void)fillInImages{ 

NSString *imageURL; 
for (int i=0; i < [dataManager.objectList count]; i++) { 
    ... 
    if ([dataManager.RelatedImages Image] == nil) { 
    //[self startDownloadFor:imageURL atIndex:[NSNumber numberWithInt:i]; // << WORKS FINE 
    [self performSelectorOnMainThread:@selector(startDownloadFor:atIndex:) withObject:(imageURL, [NSNumber numberWithInt:i]) waitUntilDone:YES]; // << CRASHES 
    ... 
    }else { 
    ... 
    } 
    ... 
} 
... 
} 

-(void)startDownloadFor:(NSString*)imageUrl atIndex:(int)indexPath{ 

NSString *indexKey = [NSString stringWithFormat:@"key%d",indexPath]; 
... 
} 

Quelle est la bonne façon de procéder?

Merci

Répondre

1

Je ne l'ai jamais vu cette syntaxe passer plus d'un objet à un sélecteur - est que le code valide objectif-c? aussi, dans votre startDownloadFor: atIndex: vous passez un NSNumber mais le type pour le second paramètre sur ce sélecteur est (int) - cela ne peut pas être bon;)

Les docs pour performSelectorOnMainThread: indiquent que le Le sélecteur ne doit prendre qu'un seul argument de type id. Vous passez un sélecteur invalide, donc je pense que cela devient très confus au sujet de l'emplacement du NSNumber.

Pour résoudre ce problème, passer un NSDictionary conatining le nombre et l'URL de l'image à savoir

NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:imageURL, @"imageURL", [NSNumber numberWithInt:i], @"number", nil]; 
[self performSelectorOnMainThread:@selector(startDownload:) withObject:dict waitUntilDone:YES]; 

et

//-(void)startDownloadFor:(NSString*)imageUrl atIndex:(int)indexPath{ 
- (void)startdownload:(NSDictionary *)dict { 
    NSURL *imageURL = [dict objectForKey:@"imageURL"]; 
    int indexPath = [[dict objectforKey:@"number"] intValue]; 
1

Vous essayez de passer 2 arguments en performSelectorOnMainThread:withObject:waitUntilDone: alors que la méthode ne supporte que le passage d'un argument.

Vous devez utiliser NSInvocation d'envoyer plus d'arguments (ou utiliser un NSDictionary comme doyen proposé).

SEL theSelector; 
NSMethodSignature *aSignature; 
NSInvocation *anInvocation; 

theSelector = @selector(startDownloadFor:atIndex:); 
aSignature = [self instanceMethodSignatureForSelector:theSelector]; 
anInvocation = [NSInvocation invocationWithMethodSignature:aSignature]; 
[anInvocation setSelector:theSelector]; 
[anInvocation setTarget:self]; 
// indexes for arguments start at 2, 0 = self, 1 = _cmd 
[anInvocation setArgument:&imageUrl atIndex:2]; 
[anInvocation setArgument:&i atIndex:3]; 

[anInvocation performSelectorOnMainThread:@selector(invoke) withObject:NULL waitUntilDone:YES];