Я пытаюсь понять, почему существуют объекты CF и NS, которые, кажется, делают одно и то же и взаимозаменяемы через бесплатное соединение. Если, скажем, CFArray и NSArray делают одно и то же, и я могу свободно переключаться между ними, какой смысл в их существовании обоих? Существуют ли эмпирические правила о том, когда использовать один над другим? Являются ли объекты CF просто устаревшими объектами из старых фреймворков? Любое понимание этого будет высоко оценено.
Объекты CF против объектов NS
- Следует отметить, что а) не все типы CF имеют эквивалент NS и наоборот, и б) не все имена, имена которых совпадают, за исключением префикса, на самом деле соединяются бесплатно;
CFBundle
иNSBundle
, например, нет. Подробнее в документах а> как всегда. 20.02.2012
Ответы:
Чтобы ответить на ваши вопросы по порядку:
Какой смысл в том, что они оба существуют? Есть несколько причин.
Если вы хотите предоставить C API, такой как Carbon API, и вам нужны такие вещи, как массивы и словари объектов с подсчетом ссылок, вам нужна библиотека, такая как Core Foundation (которая предоставляет
CFArray
), и, конечно же, она должна иметь C API.Если вы хотите написать библиотеки для сторонних разработчиков для использования в Windows (например), вам необходимо предоставить C API.
Если вы хотите написать низкоуровневую библиотеку, скажем, для взаимодействия с ядром вашей операционной системы, и вам не нужны накладные расходы на обмен сообщениями Objective-C, вам нужен C API.
Так что это веские причины для использования Core Foundation, чистой библиотеки C.
Но если вы хотите предоставить более высокий уровень и более приятный API в Objective-C, вам нужны объекты Objective-C, представляющие массивы, словари, объекты с подсчетом ссылок и так далее. Итак, вам нужен Foundation, который представляет собой библиотеку Objective-C.
Когда следует использовать тот или иной? Как правило, вы должны использовать классы Objective-C (например,
NSArray
) всякий раз, когда можете, потому что интерфейс Objective-C более приятен в использовании:myArray.count
(или[myArray count]
) легче читать и писать, чемCFArrayGetCount(myArray)
. Вы должны использовать Core Foundation API только тогда, когда это действительно необходимо: когда вы работаете на платформе, на которой нет Objective-C, или когда вам нужны функции, которые предоставляет Core Foundation API, но отсутствуют объекты Objective-C. Например, вы можете указать обратные вызовы при созданииCFArray
илиCFDictionary
, которые позволяют хранить объекты без подсчета ссылок. КлассыNSArray
иNSDictionary
не позволяют вам сделать это — они всегда предполагают, что вы храните объекты с подсчетом ссылок.Являются ли объекты CF просто устаревшими объектами? Нисколько. На самом деле, Nextstep существовал в течение многих лет только с библиотекой Objective-C Foundation и без (общедоступной) библиотеки Core Foundation. Когда Apple нужно было поддерживать как Carbon API, так и Cocoa API поверх одних и тех же средств операционной системы более низкого уровня, они создали (или обнародовали) Core Foundation для поддержки обоих.
Между прочим, часть Core Foundation имеет открытый исходный код. Вы можете найти его часть с открытым исходным кодом для Mac OS X 10.10.5 здесь: https://opensource.apple.com/source/CF/CF-1153.18/. Я нашел исходный код CFRunLoop
и CFStream
очень информативным.
Core Foundation — это C API для множества общих структур данных. У большинства этих структур данных есть эквиваленты в Cocoa, но не у всех. Большинство из эквивалентных являются бесплатными мостами, что позволяет использовать их взаимозаменяемо, но не все из них.
Бесплатный мост - это очень хитрый прием. Если вам нужны подробности, см. запись ridiculous_fish, на которую указывает @Matt Wilding. Это наиболее авторитетный источник информации по этому вопросу (и он оказал большое влияние на главу 19 iOS:PTL, в которой также объясняется, как все это работает). Но это не имеет большого значения для большинства целей. Как отмечает Мэтт, обычно можно представить, что NSArray
— это то же самое, что CFArrayRef
. Во многих случаях это не совсем так, но иногда это так, и в большинстве случаев достаточно близко. Это то же самое, что сказать, что @"stuff"
совпадает с NSString
, содержащим stuff
. В основном это правда, но не совсем так.
Когда OS 9 перешла на OS X, было очень удобно предоставлять C доступ к структурам данных, подобным Objective-C. Сегодня многие низкоуровневые фреймворки предоставляют C API из соображений производительности. Вы не должны думать о CF как о «устаревшем» или «внутреннем». Вы должны думать об этом как о низкоуровневом, и вы должны использовать его только тогда, когда вам нужна мощность, которую он предоставляет, или вы имеете дело с низкоуровневой структурой, которая требует этого.
Объекты CF часто более гибкие, чем их аналоги NS. Например, CFDictionaryRef
может содержать необъектные ключи и значения, а NSDictionary
— нет. (Конечно, они соединяются бесплатно, так что вы можете создать CFDictionaryRef
без удержания, а затем рассматривать его как NSDictionary
. Хитрость....)
По мере того как Apple выпускает новые платформы, вы заметите, что они часто сначала раскрывают API-интерфейсы C, а затем добавляют API-интерфейсы Objective-C. Это причина, по которой полезно изучить Core Foundation, даже если вы не используете его каждый день. Но когда это возможно, вы обычно должны использовать ObjC.
__NSCFConstantString
, который является (своего рода) подклассом NSString
. (Отчасти потому, что это бесплатный мостовой класс, который не совсем то же самое, что и подкласс.) Константные строки находятся в сегменте __TEXT, а не в куче (вместе с лежащей в их основе cstring, которая хранится отдельно) и они игнорируют вызовы retain
и release
. 20.02.2012 У этого вопроса есть история. Core Foundation — это мозг операции. Он написан в основном на C. Он был создан с приобретением Apple NEXT и их API и многим им обязан. Классы NS* часто представляют собой просто абстрактные интерфейсы Objective C, построенные поверх типов CF*. Итак, когда вы спрашиваете, почему существуют и CFArray, и NSArray, ответ заключается в том, что на самом деле их нет. NSArrays являются CFArrays, NSStrings являются CFStrings и т. д. Вот почему возможно бесплатное соединение.
Для более интересного и подробного чтения я бы отослал вас к этой записи в блоге.
CF означает CoreFoundation. Открытые объекты с CF в именах являются обычными объектами Core Foundation, написанными на C. Все объекты связаны бесплатным мостом со своими друзьями Cocoa Touch Foundation в стране Objective-C. Обычно это непрозрачные указатели.
NS означает NextStep, старую ОС, на которой была построена Mac OS X. Объекты с префиксом NS обычно полностью написаны на Objective-C или C или даже на C++.
Это действительно зависит от того, что вам нужно, чтобы каждый объект делал. Мне, конечно, проще работать на чистом Objective-C с NSString, чем на смеси C и Objective-C с CFString, но есть некоторые вещи, которые объекты CF могут делать, а объекты NS просто не могут. t (в основном вещи очень низкого уровня). Объекты CF также гораздо больше балуются ссылками, мутациями и проверками, чем их аналоги NS.
(Для справки в будущем существует еще несколько префиксов: CG для CoreGraphics, UI для UIKit, QL для QuickLook, AV для AVFoundation, MP для MediaPlayer, MF для MessageFoundation, GL для GLKit и MK для MapKit) (если я пропустил, с удовольствием отредактирую).