2013-03-18 2 views
-1

Mon but est de jouer une séquence de sons avec des pauses entre eux en arrière-plan, sans ralentir le thread principal/interface graphique.L'objet initialisé dans le bloc GCD a des méthodes s'exécutant dans le thread principal

Lorsque j'exécute le code à l'aide de l'instrument Time Profiler, je vois ce qui suit. L'init AudioStateMachine est envoyé à un autre thread avec GCD, tandis que les autres méthodes d'AudioStateMachine s'exécutent dans le thread principal. J'ai besoin de toutes les méthodes de AudioStateMachine pour ne pas fonctionner dans le main.

Running Time Self  Symbol Name 
87.0ms 8.7% 0.0  Main Thread 0x8531c 
84.0ms 8.4% 0.0  start 
84.0ms 8.4% 83.0   main 
1.0ms 0.1% 0.0  -[AudioStateMachine audioPlayerDidFinishPlaying:successfully:] 
1.0ms 0.1% 1.0   -[AudioStateMachine play:] 
1.0ms 0.1% 1.0  -[AudioStateMachine states] 
1.0ms 0.1% 1.0  -[AudTabController viewDidLoad] 
1.0ms 0.1% 1.0  instruments_notifier 
4.0ms 0.4% 0.0  _dispatch_worker_thread2 0x85371 
4.0ms 0.4% 1.0  __38-[ScreeningViewController viewDidLoad]_block_invoke 
3.0ms 0.3% 0.0  -[AudioStateMachine init] 
code

pour le contrôleur de vue qui distribue la tâche de fond audio:

controller.h 
@interface ScreeningViewController : UIViewController { 
    UIButton *okButton; 
    UIProgressView *bar; 
    AudioStateMachine *test; 
} 
@property(nonatomic, strong) UIButton *okButton; 
@property(nonatomic, strong) UIProgressView *bar; 

-(IBAction)okPressed:(id)sender; 
@end 

Controller.m

@implementation ScreeningViewController 
@synthesize okButton; 
@synthesize bar; 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 
{ 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    return self; 
} 

-(void)okPressed:(id) sender{ 
    NSLog(@"OK button pressed"); 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    self.view.backgroundColor = [UIColor whiteColor]; 
    //kick off state machine 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     test = [[AudioStateMachine alloc] init]; 
    }); 
} 
@end 

Et le AudioStateMachine.h:

@interface AudioStateMachine : NSObject <AVAudioPlayerDelegate> 
{ 
    AVAudioPlayer *player; 
    NSArray *soundList; 
    int index; 
} 

@property(nonatomic, strong) AVAudioPlayer *player; 
@property(nonatomic, strong) NSArray *soundList; 
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag; 
- (id)init; 
- (void)play:(int)i; 
@end 

Et le .m:

@implementation AudioStateMachine 
@synthesize player, soundList; 

-(id)init 
{ 
    if ((self = [super init])) 
    { 
     soundList = [[NSArray alloc] initWithObjects:@"1",@"2",@"3",@"4",nil]; 
     index = 0; 
     [self play:index]; 
    } 
    else 
     NSLog(@"Error initializing AudioStateMachine"); 
    return self; 
} 

-(void) play:(int)i 
{ 
    NSError *error; 
    player = [[AVAudioPlayer alloc] initWithContentsOfURL:[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:[soundList objectAtIndex:i] ofType:@"wav"]] error:&error]; 
    player.delegate = self; 
    [player prepareToPlay]; 
    [player play]; 
} 
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag 
{ 
    [NSThread sleepForTimeInterval:1.5]; 
    if (index < soundList.count) { 
     index++; 
     [NSThread sleepForTimeInterval:1.0]; 
     [self play:index]; 
    } else { 
     NSLog(@"Reached end of sound list.");//reached end of queue 
    } 
} 
@end 

J'apprécie toute aide.

+0

Veuillez expliquer pourquoi vous devez effectuer les tâches en arrière-plan. –

+0

Appelez ces méthodes à partir du thread d'arrière-plan. ou utilisez performSelector On BackGround –

Répondre

2

Les fils ne sont pas des endroits où vivent des objets - ce sont des séquences d'instructions exécutées. La création d'un objet sur un thread signifie uniquement que l'UC a exécuté le code pour configurer l'objet dans le cadre de l'exécution de ce thread particulier. Il n'a aucun impact futur sur le thread sur lequel exécuteront les méthodes d'instance de cet objet.

Si vous avez besoin que tout le travail de votre objet soit effectué sur un thread d'arrière-plan, vous pouvez implémenter toutes ses méthodes pour envoyer leur travail à une file d'attente concurrente. A titre d'exemple artificiel:

- (void)aMethod 
{ 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     // do all your method's work here… 
    }); 
} 

Aussi, dormir le fil juste pour obtenir un retard dans la lecture de la piste suivante me semble que la mauvaise approche. Il existe un certain nombre de méthodes moins perturbatrices qui sont plus conviviales avec les approches de simultanéité modernes, par exemple dispatch_after().

+0

qui clarifie mon malentendu, merci. Je vais essayer d'utiliser dispatch_after au lieu de dormir le fil. –

Questions connexes