我的目标是播放一系列声音,并在背景中暂停它们,而不会减慢主线程/ gui。
当我使用Time Profiler Instrument运行代码时,我得到以下内容。 AudioStateMachine init使用GCD调度到另一个线程,而AudioStateMachine的其他方法在主线程中运行。我需要所有AudioStateMachine的方法都不能在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]
调度音频后台任务的视图控制器的代码:
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
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
而.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
我感谢任何帮助。
答案 0 :(得分:2)
线程不是对象所在的位置 - 它们是执行的指令序列。在线程上创建对象仅意味着CPU运行代码以将对象设置为执行该特定线程的一部分。它对将运行该对象的任何实例方法的线程没有影响。
如果您需要在后台线程上完成所有对象的工作,则可以实现其所有方法以将其工作分派到并发队列。作为一个人为的例子:
- (void)aMethod
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// do all your method's work here…
});
}
另外,为了延迟播放下一首曲目而暂停线程会让我感觉不对劲。现代并发方法有许多不那么具有破坏性的方法,例如dispatch_after()
。