-1

我的目标是在后台播放一系列声音,它们之间有停顿,而不会减慢主线程/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

控制器.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

还有他们:

@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

我很感激任何帮助。

4

1 回答 1

2

线程不是对象所在的地方——它们是执行的指令序列。在线程上创建对象仅意味着 CPU 运行代码以设置对象作为其执行该特定线程的一部分。它对该对象的任何实例方法将在哪个线程上运行没有未来影响。

如果您需要在后台线程上完成所有对象的工作,您可以实现其所有方法以将它们的工作分派到并发队列。作为一个人为的例子:

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

此外,只是为了延迟播放下一首曲目而让线程休眠,这让我觉得这是错误的方法。有许多破坏性较小的方法对现代并发方法更友好,例如dispatch_after().

于 2013-03-18T09:25:38.860 回答