Короткий ответ: вы можете (см. Ответ Дэйва Делонга).Длинный ответ: ты не можешь.Оба верны.Лучший вопрос может быть: «Зачем вам нужно знать?»По моему мнению, если вы можете организовать вещи так, чтобы вам не нужно было об этом знать, вам, вероятно, будет лучше.
Я не говорю, что вы не можете этого сделать, или дажечто ты не должен.Я говорю о том, что есть некоторые скрытые ошибки, когда вы начинаете идти по этому пути, и иногда вы не совсем понимаете, что представляют собой все неустановленные предположения.К сожалению, программирование правильно зависит от знания всех мелких деталей.Вдобавок ко всему, вот несколько потенциальных ошибок:
Насколько я знаю, набор типов Core Foundation увеличивался в каждой основной версии ОС.Поэтому каждый основной выпуск ОС имеет расширенный набор типов Core Foundation предыдущих выпусков и, вероятно, строгий расширенный набор.Это «наблюдаемое поведение», а не обязательно «гарантированное» поведение.Важно отметить, что «вещи могут и будут меняться», и при всех равных условиях, более простые и простые решения, как правило, не принимают это во внимание.Как правило, считается плохим стилем программирования для кодирования чего-то, что ломается в будущем, независимо от причины или обоснования.
Из-за бесплатной связи между Базовой основой и Фондом только потому, чтоCFTypeRef = CFStringRef
не означает, что CFTypeRef ≡ CFStringRef
, где =
означает «равно», а ≡
означает «идентично».Существует различие, которое может быть или не быть важным в зависимости от контекста.Как предупреждение, это, как правило, там, где ошибки свободно перемещаются.
Например, CFMutableStringRef
можно использовать везде, где можно использовать CFStringRef
или CFStringRef = CFMutableStringRef
.Однако вы не можете использовать CFStringRef
везде, где CFMutableStringRef
можно использовать по понятным причинам.Это значит CFStringRef ≢ CFMutableStringRef
.Опять же, в зависимости от контекста, они могут быть одинаковыми, но они не идентичны.
Это очень важно отметить, что пока есть CFStringGetTypeID()
, нет соответствующего CFMutableStringGetTypeID()
.
Логически CFMutableStringRef
является строгим надмножеством CFStringRef
.Из этого следует, что передача истинного неизменяемого CFStringRef
в CFMutableString
вызов API вызовет «некоторую проблему».Хотя сейчас это может и не быть правдой (т. Е. 10.6), я точно знаю, что в прошлом было верно следующее: вызовы API CFMutableString
не проверяли, что «строковый аргумент» был действительно изменяемым (это действительно было так.для всех типов, которые делали различие между неизменяемыми и изменяемыми).Проверки были там, но они были в форме отладочных утверждений, которые были отключены в сборках "Release" (другими словами, проверки никогда не выполнялись на практике).
Это (или, возможно, было) официальноне считается ошибкой, и ( тривиальные ) проверки изменчивости были , а не , выполненными "по соображениям производительности".Не предоставлен «публичный» API для указания изменчивости указателя CFString
(или изменчивости любого типа).В сочетании с Toll-Free bridging это означало, что вы могли изменять неизменяемые объекты NSString
, даже если API NSMutableString
действительно выполняли проверку на изменяемость и вызывали «какие-то проблемы» при попытке изменить неизменяемый объект.Аромат с тем фактом, что @""
константные строки в вашем источнике отображаются во время выполнения в память только для чтения.
Официальной строкой, насколько я помню, было «не передавать неизменяемые объекты, либо CFStringRef, либо NSString»., для API CFMutableString, и далее, это было ошибкой, чтобы сделать это ".Когда было указано, что с этой позицией могут возникнуть некоторые проблемы, связанные с безопасностью (не говоря уже о том, что это было принципиально невозможно), скажите, если что-то когда-либо допустило ошибку критической зависимости от неизменности строки, особенно «хорошо известной»Струнный ответ был «проблема теоретическая, и в это время ничего не будет сделано, пока не будет продемонстрирован работоспособный эксплойт».
Обновление: Мне было интересно посмотреть, каково текущее поведение.На моей машине запуск 10.6.4 с использованием CFMutableString
API на неизменяемом CFString
приводит к тому, что неизменяемая строка становится по существу @""
, что по крайней мере лучше, чем она делала раньше (<= 10.5), и фактически изменяетстрока.Определенно не идеальное решение, имеет тот горький вкус реального мира, где его единственное искупительное качество - это «наименее худшее решение». </p>
Так что помните, будьте осторожны в своих предположениях!Вы можете сделать это, но если вы это сделаете, более важно, чтобы вы не сделали это неправильно .:) Конечно, будет работать много «неправильных» решений, поэтому тот факт, что все работает, не обязательно является доказательством того, что вы делаете это правильно.Хорошие времена!
Кроме того, в системе Duck Typed часто считается плохой формой и, возможно, даже ошибкой, чтобы "слишком внимательно посмотреть на тип объекта".Objective-C, безусловно, Duck типизированной системы, и это, безусловно, кровоточит над и ядром фонд из-за тесную связь с Toll-Free мостиков.CFTypeRef
является прямым проявлением этой двусмысленности типа утки, и в значительной степени зависит от контекста, может быть явным способом сказать: «Вы не должны слишком внимательно присматриваться к типам».