3

J'ai trouvé que comme prévu lorsque j'écrivais une image dans un fichier que mon interface utilisateur était bloquée pour la durée, ce qui n'était pas acceptable. Lorsque j'écris l'image dans un fichier, je publie une notification NS afin que je puisse faire d'autres tâches spécifiques liées à cette fin. travail d'origine, mais le code de blocage UI:Comment puis-je publier une NSNotification lors de l'utilisation de Grand Central Dispatch?

-(void)saveImageToFile { 
    NSString *imagePath = [self photoFilePath]; 
    BOOL jpgData = [UIImageJPEGRepresentation([[self captureManager] stillImage], 0.5) writeToFile:imagePath atomically:YES]; 

if (jpgData) {   
    [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:self]; 
} 

Pour éviter le blocage UI j'ai mis la writeToFile: dans une file d'attente Grand Central Dispatch il fonctionne comme un thread concurrent. Mais quand l'écriture est terminée et que le thread est terminé, je veux poster un NSNotification. Je ne peux pas car le code est montré ici parce qu'il est dans un fil de fond. Mais c'est la fonctionnalité que je veux accomplir, se rendant compte ce n'est pas un code pratique:

-(void)saveImageToFile { 
    NSString *imagePath = [self photoFilePath]; 

    // execute save to disk as a background thread 
    dispatch_queue_t myQueue = dispatch_queue_create("com.wilddogapps.myqueue", 0); 
    dispatch_async(myQueue, ^{ 
     BOOL jpgData = [UIImageJPEGRepresentation([[self captureManager] stillImage], 0.5) writeToFile:imagePath atomically:YES]; 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      if (jpgData) {   
      [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:self]; 
      } 
     }); 
    }); 
} 

Quel est le mécanisme approprié ici pour afficher cette notification pour obtenir la fonctionnalité que je veux?

Répondre

6

Quelques possibilités ici.

1)

Que diriez-vous [NSObject performSelectorOnMainThread: ...]?

E.G.

-(void) doNotification: (id) thingToPassAlong 
{ 
    [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:thingToPassAlong]; 
} 

-(void)saveImageToFile { 
    NSString *imagePath = [self photoFilePath]; 

    // execute save to disk as a background thread 
    dispatch_queue_t myQueue = dispatch_queue_create("com.wilddogapps.myqueue", 0); 
    dispatch_async(myQueue, ^{ 
     BOOL jpgData = [UIImageJPEGRepresentation([[self captureManager] stillImage], 0.5) writeToFile:imagePath atomically:YES]; 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      if (jpgData) { 
       [self performSelectorOnMainThread: @selector(doNotification:) withObject: self waitUntilDone: YES]; 
      } 
     }); 
    }); 
} 

Plus de détails à http://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/performSelectorOnMainThread:withObject:waitUntilDone:

ou 2)

achèvement Callbacks

comme on le voit à How can I be notified when a dispatch_async task is complete?

+0

Je pense que la simplicité de votre première option est incroyablement propre et claire. Je n'étais pas au courant de performSelectorOnMainThread :. Quelle belle façon de souligner le sous-thread et de travailler dans la boucle principale. Très bien. THX. – Ric

+0

Le code de la question d'origine ne fonctionne-t-il pas? Il semble que cela devrait fonctionner comme prévu, puisque vous envoyez la notification à la file d'attente principale à la fin du bloc passé à 'myQueue'. Je préfère ce modèle à l'utilisation de 'performSelector: onMainThread:' puisque vous n'écrivez pas une méthode séparée juste pour gérer votre notification. Code de nettoyage IMO. – sho

+0

Donc je suis confus maintenant avec toutes les options. NSNotificationCenter, GrandCentralDispatch-Blocks et performSelectorOnMainThread. J'ai utilisé pSOMT avec un NSOperation & Queue, mais jamais les deux premiers. Quelqu'un peut-il s'il vous plaît expliquer les différences ou les avantages? – marciokoko

1
-(void)saveImageToFile { 
    NSString *imagePath = [self photoFilePath]; 

    // execute save to disk as a background thread 
    dispatch_queue_t myQueue = dispatch_queue_create("com.wilddogapps.myqueue", 0); 
    dispatch_async(myQueue, ^{ 
     BOOL jpgData = [UIImageJPEGRepresentation([[self captureManager] stillImage], 0.5) writeToFile:imagePath atomically:YES]; 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      if (jpgData) {   
      [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:self]; 
      } 
     }); 
    }); 
} 

qui est déjà correcte. Cependant, pourquoi devez-vous utiliser la notification si vous avez déjà envoyé dispatch_get_main_queue()?

Il suffit d'utiliser

 dispatch_async(dispatch_get_main_queue(), ^{ 
      if (jpgData) {   
      //Do whatever you want with the image here 
      } 
     }); 

Quoi qu'il en soit votre solution originale est très bien. Ce n'est pas bloquant. Fondamentalement, il va enregistrer le fichier à un autre thread et une fois que c'est fait, il fera ce qu'il faut.

Tout ce que vous ferez sera effectué sur le même thread avec le thread qui appellera [[NSNotificationCenter defaultCenter] postNotificationName: kImageSavedSuccessfully object: self]; à savoir le fil principal.

Questions connexes