Строка имени файла используется без и со знаком @

В коде примера iOS SpeakHere есть пара методов в классе SpeakHereController, stopRecord а также record соответственно сохраните и инициализируйте файл для сохранения записи. Два метода обрабатывают строку имени файла немного по-разному, как вы можете видеть в следующих двух строках кода в этих методах.

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

Строка "recordedFile.caf" происходит после того, как предшествует @ подписать и один раз без. Я планирую использовать следующую конструкцию NSString для создания filename, но я не знаю, как правильно использовать результат в двух местах, упомянутых в этом пункте. Поэтому мой вопрос заключается в том, как использовать построенную строку filename в этих строках?

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

2 ответа

Решение

Пытаться

recorder->StartRecord(CFSTR([filename UTF8String]));

Разница между C API для строковых объектов (CFStringRef в Core Foundation) и Objective-C API для строковых объектов (NSString в какао).

Компилятор знает, что @"..." является строковым литералом 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 так, чтобы NSString а также CFString являются бесплатными мостами. На определенном уровне абстракции это один и тот же объект. Вы можете просто приводить типы между двумя типами свободно. С 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);
Другие вопросы по тегам