ARC を使用して、Apple の SpeakHere サンプルから AQRecorder クラスをプロジェクトに実装しています。コンパイルするには、AQRecorder インスタンス (例の SpeakHereController に相当) を制御するクラス (AQRecorderController) を作成する必要がありました。AQRecorderController はメイン ビュー コントローラーのペン先を介して接続され、プロパティとして実装されます。この問題は、プロパティが強いか弱いかに関係なく発生します。
私の問題は、View Controller をロードした直後に 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];
}