【问题标题】:Making this run while other views are in 'use'在其他视图处于“使用”状态时运行此操作
【发布时间】:2011-07-26 09:52:04
【问题描述】:

你好 好的,我有一个名为“RecordViewController”的视图,它具有录音机功能,因此一旦用户按下“录音”,它就会记录他们的声音,我还创建了一个“返回”按钮。但是一旦点击后退按钮,录音也会停止。我想要它,所以一旦用户返回,它仍在录制他们的声音。 这是我使用的代码:

.h

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudioTypes.h>


@interface RecordViewController : UIViewController <AVAudioRecorderDelegate> {

    IBOutlet UIButton * btnStart;
    IBOutlet UIButton * btnPlay;
    IBOutlet UIActivityIndicatorView * actSpinner;
    BOOL toggle;

    NSURL * recordedTmpFile;
    AVAudioRecorder * recorder;
    NSError * error;
    NSTimer *theTimer;
    IBOutlet UILabel *seconds;
    int mainInt;
    NSString *timeRemainingString;

}

@property (nonatomic,retain)IBOutlet UIActivityIndicatorView * actSpinner;
@property (nonatomic,retain)IBOutlet UIButton * btnStart;
@property (nonatomic,retain)IBOutlet UIButton * btnPlay;

- (IBAction) start_button_pressed;
- (IBAction) play_button_pressed;
-(IBAction)goBack:(id)sender;
-(void)countUp;


@end

.m

#import "RecordViewController.h"


@implementation RecordViewController
@synthesize actSpinner, btnStart, btnPlay;



-(void)countUp {

    mainInt += 1;
    seconds.text = [NSString stringWithFormat:@"%02d", mainInt];

}

-(IBAction)goBack:(id)sender; {

    [self dismissModalViewControllerAnimated:YES];
}



/*
 // The designated initializer. Override to perform setup that is required before the view is loaded.
 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
 if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
 // Custom initialization
 }
 return self;
 }
 */

/*
 // Implement loadView to create a view hierarchy programmatically, without using a nib.
 - (void)loadView {
 }
 */



// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

    //Start the toggle in true mode.
    toggle = YES;
    btnPlay.hidden = YES;

    //Instanciate an instance of the AVAudioSession object.
    AVAudioSession * audioSession = [AVAudioSession sharedInstance];
    //Setup the audioSession for playback and record. 
    //We could just use record and then switch it to playback leter, but
    //since we are going to do both lets set it up once.
    [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error: &error];
    //Activate the session
    [audioSession setActive:YES error: &error];

}



/*
 // Override to allow orientations other than the default portrait orientation.
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
 // Return YES for supported orientations
 return (interfaceOrientation == UIInterfaceOrientationPortrait);
 }
 */

- (IBAction)  start_button_pressed{


    if(toggle)
    {
        toggle = NO;
        [actSpinner startAnimating];
        [btnStart setImage:[UIImage imageNamed:@"stoprecording.png"] forState:UIControlStateNormal];
        mainInt = 0;
        theTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(countUp) userInfo:nil repeats:YES];


        btnPlay.enabled = toggle;
        btnPlay.hidden = !toggle;

        //Begin the recording session.
        //Error handling removed.  Please add to your own code.

        //Setup the dictionary object with all the recording settings that this 
        //Recording sessoin will use
        //Its not clear to me which of these are required and which are the bare minimum.
        //This is a good resource: http://www.totodotnet.net/tag/avaudiorecorder/
        NSMutableDictionary* recordSetting = [[NSMutableDictionary alloc] init];
        [recordSetting setValue :[NSNumber numberWithInt:kAudioFormatAppleIMA4] forKey:AVFormatIDKey];
        [recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey]; 
        [recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey];

        //Now that we have our settings we are going to instanciate an instance of our recorder instance.
        //Generate a temp file for use by the recording.
        //This sample was one I found online and seems to be a good choice for making a tmp file that
        //will not overwrite an existing one.
        //I know this is a mess of collapsed things into 1 call.  I can break it out if need be.
        recordedTmpFile = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent: [NSString stringWithFormat: @"%.0f.%@", [NSDate timeIntervalSinceReferenceDate] * 1000.0, @"caf"]]];
        NSLog(@"Using File called: %@",recordedTmpFile);
        //Setup the recorder to use this file and record to it.
        recorder = [[ AVAudioRecorder alloc] initWithURL:recordedTmpFile settings:recordSetting error:&error];
        //Use the recorder to start the recording.
        //Im not sure why we set the delegate to self yet.  
        //Found this in antother example, but Im fuzzy on this still.
        [recorder setDelegate:self];
        //We call this to start the recording process and initialize 
        //the subsstems so that when we actually say "record" it starts right away.
        [recorder prepareToRecord];
        //Start the actual Recording
        [recorder record];
        //There is an optional method for doing the recording for a limited time see 
        //[recorder recordForDuration:(NSTimeInterval) 10]

    }
    else
    {
        toggle = YES;
        [actSpinner stopAnimating];
        [btnStart setImage:[UIImage imageNamed:@"recordrecord.png"] forState:UIControlStateNormal];
        btnPlay.enabled = toggle;
        btnPlay.hidden = !toggle;
        [theTimer invalidate];

        NSLog(@"Using File called: %@",recordedTmpFile);
        //Stop the recorder.
        [recorder stop];
    }
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

-(IBAction) play_button_pressed{

    //The play button was pressed... 
    //Setup the AVAudioPlayer to play the file that we just recorded.
    AVAudioPlayer * avPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:recordedTmpFile error:&error];
    [avPlayer prepareToPlay];
    [avPlayer play];

}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    //Clean up the temp file.
    NSFileManager * fm = [NSFileManager defaultManager];
    [fm removeItemAtPath:[recordedTmpFile path] error:&error];
    //Call the dealloc on the remaining objects.
    [recorder dealloc];
    recorder = nil;
    recordedTmpFile = nil;
}

- (void)dealloc {
    [super dealloc];
}

@end

谢谢

【问题讨论】:

    标签: iphone objective-c xcode voice


    【解决方案1】:

    您需要一个共享对象,您的应用程序可以在录制过程中访问该对象。类似于

    @interface UserRecording : NSObject
    
    +(UserRecording*)currentRecording;
    
    @end
    

    如果您想正确实施,您将需要考虑所有有趣的threading 原则以及委托和/或通知。

    【讨论】:

    • 用户录制?所以我必须为此创建一个新类?
    • 我会推荐。按下开始按钮后,您可以开始音频会话。一旦开始录制,currentRecording 就可以返回该实例,直到它停止。显然会有更多的方法,比如开始/停止。
    • 我不太清楚该怎么做,我对此还是有点陌生​​
    • 试用 Mike 的解决方案。关键是您用来播放音频的任何对象只需要存在,而所有相关视图都是可见的。假设您有 3 个控制器,控制器 2 和 3 应该录制音频,但控制器 3 具有录制音频的按钮。控制器 2 可以创建音频对象(不播放),然后将其传递给控制器​​ 3。然后控制器 3 可以开始或停止录制,当控制器 3 被关闭时,它仍然会在 2 上播放。一旦控制器 2 被释放,它就不会录制控制器 1,因为它不是设计来的。希望有帮助
    【解决方案2】:

    由于您是在模态对话框内创建 AudioSession,因此当您关闭该模态对话框时,它将被解除分配。尝试在主 VC 中实例化 AudioSession,将其传递给模态 VC,然后从那里启动它。

    【讨论】:

    • 我想我会退后一步,问一下你的模态对话框的目的是什么?是向用户展示按钮吗?在这种情况下,我会使用 UIAlert 或 UIActionSheet,甚至可能是 UIButtons(切换 .hidden 属性),然后在当前启动模式对话框的任何视图控制器中执行所有操作。
    • 嗯,为什么需要 UIAlert,因为在用户按下录制按钮后,一旦用户转到另一个视图,录制仍将继续录制。什么是模态对话框,recorderviewcontroller?谢谢
    • UIAlert 只是一种方便的方式,让您可以为用户提供一些选择(例如“开始录制”)。由于您在 back 方法中取消了模态 VC,所以在哪里调用“presentModalViewController”?那是需要创建(并拥有)您的 AudioRecorder 的对象。
    猜你喜欢
    • 2020-03-09
    • 1970-01-01
    • 1970-01-01
    • 2020-11-01
    • 1970-01-01
    • 2012-10-09
    • 2015-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多