0

iOS SpeakHere のサンプル コードSpeakHereControllerには、 Classに一対のメソッドがstopRecordありrecord、それぞれが録音を保存するためのファイルを保存および初期化します。次の 2 行のコードでわかるように、2 つのメソッドではファイル名文字列の処理が少し異なります。

recordFilePath = (CFStringRef)[NSTemporaryDirectory() stringByAppendingPathComponent: @"recordedFile.caf"];
recorder->StartRecord(CFSTR("recordedFile.caf"));

文字列は、記号"recordedFile.caf" の前に@1 回、記号なしで 1 回発生します。次の NSString コンストラクトを使用して を生成する予定ですfilenameが、この段落で言及されている 2 つの場所で結果を正しく使用する方法がわかりません。だから私の質問はfilename、それらの行で構築された文字列を使用する方法ですか?

@property int counter;
NSString *filename = [[NSString alloc] initWithFormat:@"recordedFile%d.caf",self.counter];
4

2 に答える 2

1

試す

recorder->StartRecord(CFSTR([filename UTF8String]));
于 2014-08-13T01:34:06.147 に答える
0

違いは、文字列オブジェクト用の C API ( CFStringRefCore Foundation) と文字列オブジェクト用の Objective-C API ( NSStringCocoa) の違いです。

コンパイラはそれ@"..."が Objective-C 文字列リテラルであることを認識し、 (のプライベート サブクラス) の静的インスタンスを構築しますNSString

CFStringコンパイラは、リテラルについて同様のネイティブの知識を正確に持っているわけではありません。代わりに、Apple のヘッダーはCFSTR()プリプロセッサ マクロを定義して、C スタイルの文字列を Core Foundation 文字列にラップします。マクロに渡される引数は、C 文字列リテラル (例: "foo") でなければなりません。非リテラル C 文字列ポインターを返すランタイム式を渡す他の回答の構文は正しくないだけでなく、コンパイルできるとは思いません。コンパイラによっては、実行時の式ではなくCFSTR()、実際のコンパイル時のオブジェクトが生成される場合があります。CFString

つまり:@"recordedFile.caf"NSStringリテラル、CFSTR("recordedFile.caf")は C 文字列リテラルを に変換したものCFStringRefです。CFString文字どおりと考えればいいのです。

幸いなことに、Apple は Core Foundation と Cocoa を設計して、NSStringCFStringが無料でブリッジされるようにしました。それらは、特定の抽象化レベルでは、同じ種類のオブジェクトです。2 つの型の間で自由に型キャストすることができます。ARC では、このような型キャストには、変更のメモリ管理について ARC に知らせるブリッジが必要です。

したがって、次のことができます。

CFStringRef cfstring = CFSTR("recordedFile.caf");
NSString* nsstring = (__bridge NSString*)cfstring;

または:

NSString* nsstring = @"recordedFile.caf";
CFStringRef cfstring = (__bridge CFStringRef)nsstring;

あなたの特定のケースでは:

recorder->StartRecord((__bridge CFStringRef)filename);
于 2014-08-13T03:13:30.760 に答える