0

私は初めて使用dispatch_queue_tし、アプリに2つの問題があり、GCDを使用して解決できると思います。1 つ目は、メイン ビュー (ViewController) に、別のクラス (AudioViewController) によって実現されるラベルがあり、ViewController でユーザー インタラクションを行うと、ラベルの実現が停止することです。dispatch_queue_tこの問題を使用すると、解決されます。

2 つ目は、コントリビューションを押すと同じメイン ビュー (ViewController) で別のクラス (ContributionViewController) を呼び出し、このクラスは常に更新される別のクラス (AudioViewController) のインスタンス変数だけにアクセスすることです。コントリビューションを開始すると、ループを作成して複数の値を取得し、それらを使用して計算を行いましたが、それらの値はすべて同じです。

ここにいくつかのコードを入れて、物事をクリアしようとします。

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私の問題を解決することであり、それをどのように行うのですか?dispatch_queue_tAudioViewController、ContributionViewController、および ViewControllerを配置しようとしましたが、1 つ目はラベルを更新せず、2 つ目はクラッシュし、3 つ目はラベルの値が 0 のままです。

この問題を解決するためのヒントをありがとう。

編集01: mapView、デシベル ラベル、Contribution ボタンを備えた ViewController

デシベル ラベルは常に変化します。

4

1 に答える 1

0

わかりました、これは理にかなっています。mapView、contribution などの言語がわかりませんでした。それは完全に不可解でしたが、私はあなたの質問を理解し始めていると思います. 私が理解しているように、あなたの質問は、ユーザー インターフェイスが更新されていない理由です。わかりました、あなたの質問に対する大きな答えは、GCD が必要ない場合は必要ないということです。はNSTimer必要なことを行います。

今、継続的に更新されている db フィールドが更新されなくなったとあなたは言います。続けてはいけない理由は絶対にありません。試してみましたが、うまくいきます。そこで何かが起こっています。個人的には、UI を更新している NSTimer を取得した場合は、必ず でオフにしviewDidDisappear(UI が表示されていない場合は UI を更新しても意味がありません)、常に でオンにしviewDidAppearます。これを行ったとき、データベース番号でメインビューに戻るたびに、喜んで再開しました. または、別のビュー コントローラーで通知を受け取りたい場合は、デリゲートを使用してオンに戻しました。

それは次のようになります。

まず、デリゲート プロトコルが必要になる可能性があります。

//  DecibelNotifierDelegate.h

#import <Foundation/Foundation.h>

@protocol DecibelNotifierDelegate <NSObject>

@required

- (void)decibelNotifierUpdate:(CGFloat)db;

@end

次に、DecibelNotifier クラスを定義します。

//  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行いviewWillDisappearます。dbNotifier を他のビュー コントローラーに渡すこともでき、それらも通知を受け取ることができます。

私が言ったように、私はこれを試してみましたが、通知を取得したいビューコントローラーはそれをオンにしてデリゲートとして指定するだけで問題なく動作し、レースに出かけることができます.

于 2012-07-17T07:53:23.350 に答える