Строка имени файла используется без и со знаком @
В коде примера 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 ответа
Разница между 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);