在GCD块中初始化的对象具有在主线程中执行的方法

时间:2013-03-18 09:01:10

标签: iphone ios objective-c grand-central-dispatch

我的目标是播放一系列声音,并在背景中暂停它们,而不会减慢主线程/ 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

我感谢任何帮助。

1 个答案:

答案 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()

相关问题