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.
Veuillez expliquer pourquoi vous devez effectuer les tâches en arrière-plan. –
Appelez ces méthodes à partir du thread d'arrière-plan. ou utilisez performSelector On BackGround –