2009-04-18 6 views
9

J'ai un NSInvocationOperation qui téléchargerait et analyserait une série de NSXMLDocuments en arrière-plan à mon interface utilisateur sensible.Comment arrêter un NSInvocationOperation?

Ma tentative d'arrêt de l'opération d'invocation consiste à appeler cancellAllOperations de mon NSOperationQueue. Mais il semble que cela n'arrêtera pas l'exécution de l'invocation.

Des idées sur comment j'irais à propos de ce problème?

Répondre

3

C'est à la mise en œuvre de votre NSOperation objet à réellement arrêter ce qu'il fait, nettoyer, et quitter quand il est informé qu'il a été annulé. Si vous souhaitez annuler toutes les opérations de la file d'attente, la file d'attente arrêtera la mise en file d'attente des nouvelles opérations et enverra le message d'annulation aux opérations en cours.

Dans la méthode principale de votre opération, vous devez vérifier isCancelled et gérer cet état lorsque vous êtes réellement annulé.

Pour plus d'informations, voir le Creating and Managing Operation Objects dans le Guide de programmation Threading.

+0

Mais voir les autres réponses, il semble que vous ne pouvez pas le faire (au moins de la manière standard de vérifier 'isCancelled') en utilisant un' NSInvocationOperation'. – jrdioko

5

Le message ci-dessus est génial, mais pour répondre plus directement à la question d'origine: il semble que vous ne puissiez pas arrêter l'objet NSInvocationOperation car il ne prend pas en charge les annulations. Vous allez devoir le sous-classer.

11

MISE À JOUR: Les instruments montrent des fuites-un-abondance quand je fais ceci. Procéder avec prudence! Je garde ceci ici au cas où je suis sur quelque chose et quelqu'un d'autre peut comprendre comment surmonter l'obstacle de fuite.

est ici une idée tordue que je suis re-essayer que je tape ceci:

Définissez l'opération comme objet pour NSInvocationOperation « s initWithTarget: sélecteur: objet: méthode. En supposant que vous avez déjà un NSOperationQueue (nous l'appellerons file d'attente):

NSInvocationOperation *operation = [NSInvocationOperation alloc]; 
operation = [operation initWithTarget:self selector:@selector(myOperation:) object:operation]; 
[queue addOperation:operation]; 
[operation release]; 

Notez que nous devons briser le alloc dans son propre appel. Sinon, nous ne pouvons pas définir objet à opération!

Puis, dans le cadre de votre méthode d'opération, réexécutez l'objet et saupoudrez les contrôles isCancelled comme vous le souhaitez. Par exemple:

- (void)myOperation:(id)object { 
    NSInvocationOperation *operation = (NSInvocationOperation *)object; 
    if ([operation isCancelled]) return; 
    ... 
    } 

Assurez-vous que votre sélection se termine par deux points dans le dos initWithTarget: ... appel, puisque vous passerez dans un objet maintenant.

Jusqu'ici, tout va bien. Maintenant, si je peux forcer cancelAllOperations, je saurai si cela fonctionne réellement. :)

+0

Ne l'essaiera pas à cause de fuites. Mais l'idée est géniale! –

8

Vous devez vérifier si NSInvocationOperation isCancelled est YES. Pour faire cela NSInvocationOperation, vous pouvez utiliser d'observation de la valeur clé:

Ajoutez votre objet en tant qu'observateur NSInvocationOperation isCancelled lors de l'exécution de l'opération:

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:<targetObj> selector:@selector(<targetMethod>) object:nil]; 
[operation addObserver:<targetObj> forKeyPath:@"isCancelled" options:NSKeyValueObservingOptionNew context:nil]; 
[operQueue addOperation:operation]; 
[operation release]; 

Puis, en targetObj mettre en œuvre

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context; 

regarder car isCancelled est modifié par cancellAllOperations de NSOperationQueue. Vous pouvez définir un indicateur privé ici et targetMethod peut le vérifier et l'annuler si nécessaire.

Questions connexes