我正在使用 ARC 将 Apple 的 SpeakHere 示例中的 AQRecorder 类实现到我的项目中。为了让它编译,我必须创建一个类 (AQRecorderController) 来控制 AQRecorder 实例(相当于示例中的 SpeakHereController)。AQRecorderController 通过我的主视图控制器的 nib 连接并作为属性实现。无论属性是强还是弱,都会出现问题。
我的问题是加载视图控制器后不久,AQRecorderController 被释放,但仅在设备上测试时。在模拟器中,这不会发生。它发生在 iPad 和 iPhone、iOS 5 和 iOS 6 上。出于录制目的,我需要在视图控制器的整个生命周期中维护此引用(您不能在录制时删除录制器并期望有一个完成的文件)。
有没有人遇到过这个或类似的事情?如果 AQRecorderController 属性很强,我在尝试使用它时会遇到错误的访问错误,如果它很弱,我只会得到一个 nil,并且它无法使用。
任何帮助将不胜感激。
formViewController.h:
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
@class AQRecorderController;
@interface formViewController : UIViewController <UIActionSheetDelegate, UITableViewDelegate, UIGestureRecognizerDelegate> {
IBOutlet AQRecorderController *aqRecorderController;
}
@property (nonatomic, weak) IBOutlet AQRecorderController *aqRecorderController;
@end
AQRecorderController.h
#import <Foundation/Foundation.h>
#import "AQRecorder.h"
@interface AQRecorderController : NSObject
{
AQRecorder *aqRecorder;
}
@property (readonly) AQRecorder* aqRecorder;
@property (nonatomic, assign) bool isRecording;
@property (nonatomic, strong) NSString* fileName;
-(bool)startRecording;
-(bool)pauseRecording;
-(bool)stopRecording;
-(bool)initializeRecordSettingsWithCompression:(bool)compressionEnabled;
@end
这是 AQRecorderController 释放后的堆栈跟踪:
2012-10-23 10:34:09.600 TestApp[510:907] (
0 TestApp 0x000f32ab
-[AQRecorderController dealloc] + 138
1 CoreFoundation 0x32247311 CFRelease + 100
2 CoreFoundation 0x3225195d <redacted> + 140
3 libobjc.A.dylib 0x31ad5489 <redacted> + 168
4 CoreFoundation 0x32249441 _CFAutoreleasePoolPop + 16
5 Foundation 0x37303a7f <redacted> + 466
6 CoreFoundation 0x322db5df <redacted> + 14
7 CoreFoundation 0x322db291 <redacted> + 272
8 CoreFoundation 0x322d9f01 <redacted> + 1232
9 CoreFoundation 0x3224cebd CFRunLoopRunSpecific + 356
10 CoreFoundation 0x3224cd49 CFRunLoopRunInMode + 104
11 GraphicsServices 0x32fb52eb GSEventRunModal + 74
12 UIKit 0x34e92301 UIApplicationMain + 1120
13 TestApp 0x00081a9d main + 48
14 TestApp 0x0005aa68 start + 40
)
这是记录器实例化的地方。
AQRecorderController.mm:
- (void)awakeFromNib
{
aqRecorder = new AQRecorder();
}
这是使用录音机的地方。至此,AQRecorderController 已被释放,并且此代码永远不会执行(它会导致崩溃,因为 AQRecorderController 已被释放)。
-(bool)startRecording
{
if (aqRecorder->IsRunning())
{
[self stopRecording];
}
else // If we're not recording, start.
{
@try
{
// Start the recorder
CFStringRef filenameString = (CFStringRef)CFBridgingRetain(self.fileName);
aqRecorder->StartRecord(filenameString);
}
@catch(NSException *ex)
{
NSLog(@"Error: %@", [ex description]);
return NO;
}
[self setFileDescriptionForFormat:aqRecorder->DataFormat() withName:@"Recorded File"];
}
[self checkIfRecording];
return YES;
}
这里是 AQRecorderController 实例化的地方。
formViewController.mm:
//this is called in viewDidAppear
-(void)initializeAQRecorder: (NSString*)soundFileName
{
aqRecorderController = [[AQRecorderController alloc] init];
NSLog(@"AQRecorderController is being initialized for file %@",soundFileName);
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *soundFilePath =[[NSString alloc] initWithFormat:@"%@",[documentsDir stringByAppendingPathComponent:soundFileName]];
[aqRecorderController setFileName:soundFilePath];
[aqRecorderController initializeRecordSettingsWithCompression:NO];
}