Dispatch_queue问题

时间:2012-07-17 00:18:48

标签: ios multithreading ios5 grand-central-dispatch

我是dispatch_queue_t的新用户,我的应用程序存在两个问题,我认为可以使用GCD解决。第一个是在主视图(ViewController)中我有一个标签,由另一个类(AudioViewController)实现,当我在ViewController中进行任何用户交互时,标签停止实现,所以我想如果我使用{{1这个问题将得到解决。

第二件事是在同一主视图(ViewController)中,当我按下一个贡献时,我调用另一个类(ContributionViewController),这个类只访问另一个类的实例变量(AudioViewController),它一直刷新。当我开始贡献时,我做了一个循环以获得多个值来与它们进行一些微积分,但这些值都是相同的。

我会在这里放一些代码来试图清除这些东西。

dispatch_queue_t

ViewController.m

- (IBAction)makeContribution:(id)sender { NSLog(@"A: Contribution button clicked"); NSLog(@"-= START CONTRIBUTION =-"); cvc = [[ContributionViewController alloc] init]; cvc.avc = self.avc; // Get NUM_CONTRIBUTIONS contributions to make average. int contContribution; for (contContribution = 0; contContribution < NUM_CONTRIBUTIONS; contContribution++) { [cvc getEachContribution]; } // Make average [cvc makeAverage:NUM_CONTRIBUTIONS]; [cvc release]; }

AudioViewController.m

- (void)audioInitializationWithTimeInterval:(float)time { NSDictionary* recorderSettings = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kAudioFormatLinearPCM],AVFormatIDKey, [NSNumber numberWithInt:44100],AVSampleRateKey, [NSNumber numberWithInt:1],AVNumberOfChannelsKey, [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey, [NSNumber numberWithBool:NO],AVLinearPCMIsBigEndianKey, [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey, nil]; NSError* error; NSURL *url = [NSURL fileURLWithPath:@"/dev/null"]; recorder = [[AVAudioRecorder alloc] initWithURL:url settings:recorderSettings error:&error]; //enable measuring //tell the recorder to start recording: [recorder record]; if (recorder) { [recorder prepareToRecord]; recorder.meteringEnabled = YES; [recorder record]; levelTimer = [NSTimer scheduledTimerWithTimeInterval:time target:self selector:@selector(levelTimerCallback:) userInfo:nil repeats:YES]; } else NSLog(@"%@",[error description]); } - (void)levelTimerCallback:(NSTimer *)timer { //NSLog(@"-= AVC =-"); [recorder updateMeters]; db = [recorder averagePowerForChannel:0] - DBOFFSET; db += 120; db = db < 0 ? 0 : db; vc.lab_decibel.text = [NSString stringWithFormat:@"%0.0f", db]; }

ContributionViewController.m

所以,主要的是- (void)getEachContribution { actualContribution = self.avc.db; NSLog(@"Actual contribution: %f", actualContribution); NSLog(@"Sum before: %0.2f", sumContribution); sumContribution += actualContribution; NSLog(@"Sum After: %0.2f", sumContribution); } - (void)makeAverage:(int)numOfContributions { self.average = self.sumContribution / numOfContributions; NSLog(@"Average: %0.2f", self.average); } 将解决我的问题以及如何做到这一点?我试图将dispatch_queue_t放在AudioViewController,ContributionViewController和ViewController上,但是第一个没有更新标签,第二个没有崩溃,第三个标签仍然是0值。

感谢您解决此问题的任何提示。

编辑01: ViewController with mapView, decibel label and Contribution button

分贝标签一直在变化。

1 个答案:

答案 0 :(得分:0)

好的,这开始有意义了。我不懂mapView,贡献等语言。这完全是神秘的,但我想我已经开始理解你的问题了。据我了解,您的问题是您的用户界面未更新的原因。好的,你的问题的最大答案是,如果你不想,你不需要GCD。 NSTimer可以满足您的需求。

现在,您说不再更新您不断更新的数据库字段。绝对没有理由不继续这样做。我试过了,它运行正常。那里有些事情发生了。就个人而言,当我有一个正在更新我的用户界面的NSTimer时,我确保在viewDidDisappear中将其关闭(如果不可见,则无需更新您的用户界面)并始终在{{1}中启用它}。当我这样做时,每当我使用db编号返回主视图时,它就会愉快地恢复。或者如果我想要另一个视图控制器来获取通知,我只是使用委托将其重新打开。

这可能如下所示。

首先,您可能需要委托协议:

viewDidAppear

然后,您想要定义DecibelNotifier类:

//  DecibelNotifierDelegate.h

#import <Foundation/Foundation.h>

@protocol DecibelNotifierDelegate <NSObject>

@required

- (void)decibelNotifierUpdate:(CGFloat)db;

@end

//  DecibelNotifier.h

#import <Foundation/Foundation.h>
#import "DecibelNotifierDelegate.h"

@interface DecibelNotifier : NSObject

@property (nonatomic, retain) id<DecibelNotifierDelegate> delegate;
@property CGFloat db;

- (void)startWithInterval:(float)time target:(id<DecibelNotifierDelegate>)delegate;
- (void)stop;

@end

因此,第一个想要通知的视图控制器可能具有属性:

//  DecibelNotifier.m

#import "DecibelNotifier.h"
#import "AVFoundation/AVFoundation.h"

@interface DecibelNotifier ()
{
    AVAudioRecorder *_recorder;
    NSTimer *_levelTimer;
}
@end

// note, your code makes reference to DBOFFSET and I don't know what that is. Update this following line accordingly.

#define DBOFFSET 0

@implementation DecibelNotifier

@synthesize delegate = _delegate;
@synthesize db = _db;

- (id)init
{
    self = [super init];
    if (self)
    {
        NSDictionary* recorderSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                          [NSNumber numberWithInt:kAudioFormatLinearPCM],AVFormatIDKey,
                                          [NSNumber numberWithInt:44100],AVSampleRateKey,
                                          [NSNumber numberWithInt:1],AVNumberOfChannelsKey,
                                          [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,
                                          [NSNumber numberWithBool:NO],AVLinearPCMIsBigEndianKey,
                                          [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
                                          nil];
        NSError* error;

        NSURL *url = [NSURL fileURLWithPath:@"/dev/null"];
        _recorder = [[AVAudioRecorder alloc] initWithURL:url settings:recorderSettings error:&error];

        if (!_recorder)
            NSLog(@"%@",[error description]);
    }

    return self;
}

- (void)startWithInterval:(float)time target:(id<DecibelNotifierDelegate>)delegate
{
    if (_recorder) 
    {
        self.delegate = delegate;

        [_recorder prepareToRecord];
        _recorder.meteringEnabled = YES;
        [_recorder record];

        _levelTimer = [NSTimer scheduledTimerWithTimeInterval:time target:self selector:@selector(levelTimerCallback:) userInfo:nil repeats:YES];
    }
}

- (void)stop
{
    [_recorder stop];

    [_levelTimer invalidate];
    _levelTimer = nil;

    self.delegate = nil;
}

- (void)levelTimerCallback:(NSTimer *)timer
{
    [_recorder updateMeters];

    CGFloat db = [_recorder averagePowerForChannel:0] - DBOFFSET;
    db += 120;
    db = db < 0 ? 0 : db;

    _db = db;

    [self.delegate decibelNotifierUpdate:db];
}

@end

您可以使用以下命令对其进行初始化:

@property (strong, nonatomic) DecibelNotifier *dBNotifier;

然后,您可以使用以下命令启用通知

self.dBNotifier = [[DecibelNotifier alloc] init];

所以问题是当你打开和关闭这些通知时。我在[self.dBNotifier startWithInterval:0.25 target:self]; viewWillAppear中执行此操作。您也可以将dbNotifier传递给其他视图控制器,它们也可以收到通知。

就像我说的那样,我尝试了这个并且它工作正常,任何想要获得通知的视图控制器都可以打开它并将自己指定为委托,并且你将参加比赛。