Доступ к содержанию пакета
При записи основанного на пакете кода Вы никогда не используете строковые константы для обращения к расположению файлов в пакете. Вместо этого Вы используете NSBundle
класс или CFBundleRef
непрозрачный тип для получения пути к файлу Вы хотите. Причина состоит в том, что путь к желаемому файлу может варьироваться в зависимости от родного языка пользователя и поддерживаемых локализаций пакета. Позволяя пакету определить расположение файла, Вы всегда уверены в загрузке корректного файла.
Эта глава показывает Вам, как использовать NSBundle
класс и CFBundleRef
непрозрачный тип, чтобы определить местоположение файлов и получить другую информацию о Вашем пакете. Несмотря на то, что эти типы не являются непосредственно взаимозаменяемыми, они обеспечивают сопоставимые функции. И по крайней мере в приложениях Objective C, можно использовать, какой бы ни тип удовлетворяет потребностям.
Определение местоположения и открытие пакетов
Прежде чем можно будет получить доступ к ресурсам пакета, необходимо сначала получить надлежащее NSBundle
объект или CFBundleRef
непрозрачный тип. Следующие разделы обрисовывают в общих чертах различные способы, которыми можно получить ссылку на один из этих типов.
Получение основного пакета
Основной пакет является пакетом, содержащим код и ресурсы для запущенного приложения. Если Вы - разработчик приложений, это - обычно используемый пакет. Основной пакет является также самым простым получить, потому что он не требует, чтобы Вы предоставили любую информацию.
Для получения основного пакета в приложении Какао вызовите mainBundle
метод класса NSBundle
класс, как показано в Перечислении 3-1.
Перечисление 3-1 , Добирающееся ссылку на основной пакет с помощью Какао
NSBundle* mainBundle; |
// Get the main bundle for the app. |
mainBundle = [NSBundle mainBundle]; |
Если Вы пишете приложение на базе С, можно использовать CFBundleGetMainBundle
функция для получения основного пакета для приложения, как показано в Перечислении 3-2.
Перечисление 3-2 , Добирающееся ссылку на основной пакет с помощью Базовой Основы
CFBundleRef mainBundle; |
// Get the main bundle for the app |
mainBundle = CFBundleGetMainBundle(); |
При получении основного пакета это - все еще хорошая идея удостовериться значение, которое Вы возвращаете, представляет допустимый пакет. При получении основного пакета из любого приложения возвращенное значение могло бы быть NULL
в следующих ситуациях:
Если программа не связывается, пытание получить основной пакет могло бы возвратить a
NULL
значение. Код пакета может попытаться создать основной пакет для представления содержания программы, но выполнение так не возможно во всех случаях.Если агент полный путь к исполнимой программе программы в, запустивший программу не указывал
argv
параметры, основное значение пакета могло бы бытьNULL
. Пакеты полагаются на любого путь к исполнимой программе, находящейся вargv[0]
или присутствие пути исполнимой программы вPATH
переменная окружения. Если ни один из них не присутствует, подпрограммы пакета не могли бы быть в состоянии найти основной каталог пакета. Программы, запущенныеxinetd
часто испытывайте эту проблему когдаxinetd
изменяет текущий каталог на/
.
Получение пакетов путем
Если Вы хотите получить доступ к пакету кроме основного пакета, можно создать надлежащий объект пакета, если Вы знаете путь к каталогу пакета. Создание пакета путем полезно в ситуациях, где Вы определяете платформы или другие загружаемые пакеты и знаете заранее, где будут расположены те пакеты.
Для получения пакета в определенном пути с помощью Какао вызовите bundleWithPath:
метод класса NSBundle
класс. (Можно также использовать initWithPath:
метод экземпляра инициализировать новый объект пакета.) Этот метод берет строковый параметр, представляющий полный путь каталогу пакета. Перечисление 3-3 показывает пример что доступы пакет в локальном каталоге.
Перечисление 3-3 , Располагающееся пакета Какао с помощью его пути
NSBundle* myBundle; |
// Obtain a reference to a loadable bundle. |
myBundle = [NSBundle bundleWithPath:@"/Library/MyBundle.bundle"]; |
Для получения пакета в определенном пути с помощью Базовой Основы вызовите CFBundleCreate
функция. При указании расположения пути в Базовой Основе необходимо сделать настолько использующий a CFURLRef
ввести. Перечисление 3-4 показывает пример, берущий фиксированный каталог от предыдущего примера, преобразовывающий его в URL и использующий тот URL для доступа к пакету.
Перечисление 3-4 , Располагающееся Базового пакета Основы с помощью его пути
CFURLRef bundleURL; |
CFBundleRef myBundle; |
// Make a CFURLRef from the CFString representation of the |
// bundle’s path. |
bundleURL = CFURLCreateWithFileSystemPath( |
kCFAllocatorDefault, |
CFSTR("/Library/MyBundle.bundle"), |
kCFURLPOSIXPathStyle, |
true ); |
// Make a bundle instance using the URLRef. |
myBundle = CFBundleCreate( kCFAllocatorDefault, bundleURL ); |
// You can release the URL now. |
CFRelease( bundleURL ); |
// Use the bundle... |
// Release the bundle when done. |
CFRelease( myBundle ); |
Получение пакетов в известных каталогах
Даже если Вы не знаете точный тракт к пакету, можно все еще искать его в некотором известном расположении. Например, приложение с a PlugIns
каталог мог бы хотеть получить список всех пакетов в том каталоге. Как только у Вас есть путь к каталогу, можно использовать надлежащие подпрограммы, чтобы выполнить итерации того каталога и возвратить любые пакеты.
Самый простой способ найти все пакеты в определенном каталоге состоит в том, чтобы использовать CFBundleCreateBundlesFromDirectory
функция. Эта функция новые возвраты CFBundleRef
типы для всех пакетов в данном каталоге. Перечисление 3-5 показывает, как Вы использовали бы эту функцию для получения всех плагинов в приложении PlugIns
каталог.
Перечисление 3-5 Получая ссылки пакета для ряда плагинов
CFBundleRef mainBundle = CFBundleGetMainBundle(); |
CFURLRef plugInsURL; |
CFArrayRef bundleArray; |
// Get the URL to the application’s PlugIns directory. |
plugInsURL = CFBundleCopyBuiltInPlugInsURL(mainBundle); |
// Get the bundle objects for the application’s plug-ins. |
bundleArray = CFBundleCreateBundlesFromDirectory( kCFAllocatorDefault, |
plugInsURL, NULL ); |
// Release the CF objects when done with them. |
CFRelease( plugInsURL ); |
CFRelease( bundleArray ); |
Получение пакетов идентификатором
Определение местоположения пакетов с помощью идентификатора пакета является эффективным способом определить местоположение пакетов, ранее загруженных в память. Идентификатор пакета является строкой, присвоенной CFBundleIdentifier
введите пакет Info.plist
файл. Эта строка обычно форматируется с помощью нотации обратного DNS, чтобы предотвратить конфликты пространства имен с разработчиками в других компаниях. Например, плагин Средства поиска от Apple мог бы использовать строку com.apple.Finder.MyGetInfoPlugin
как его идентификатор пакета. Вместо того, чтобы передать указатель на пакет возражают вокруг Вашего кода, клиенты, которым нужна ссылка на пакет, могут просто использовать идентификатор пакета для получения его.
Для получения пакета с помощью идентификатора пакета в Какао вызовите bundleWithIdentifier:
метод класса NSBundle
класс, как показано в Перечислении 3-6.
Перечисление 3-6 , Располагающееся пакета с помощью его идентификатора в Какао
NSBundle* myBundle = [NSBundle bundleWithIdentifier:@"com.apple.myPlugin"]; |
Перечисление 3-7 показывает, как получить пакет с помощью его идентификатора пакета в Базовой Основе.
Перечисление 3-7 , Располагающееся пакета с помощью его идентификатора в Базовой Основе
CFBundleRef requestedBundle; |
// Look for a bundle using its identifier |
requestedBundle = CFBundleGetBundleWithIdentifier( |
CFSTR("com.apple.Finder.MyGetInfoPlugIn") ); |
Помните, что можно только использовать идентификатор пакета для определения местоположения уже открытого пакета. Например, Вы могли использовать этот метод для открытия основного пакета и пакетов для всех статически соединенных платформ. Вы не могли использовать этот метод для получения ссылки на еще не загруженный плагин.
Поиск связанных пакетов
Если Вы пишете приложение Какао, можно получить список пакетов, связанных с приложением путем вызова allBundles
и allFrameworks
методы класса NSBundle
. Эти методы создают массив NSBundle
объекты, соответствующие пакетам или платформам, использующимся в настоящее время Вашим приложением. Можно использовать эти методы в качестве функций удобства, а не поддержать набор загруженных пакетов сами.
bundleForClass:
метод класса, иначе получают связанную информацию пакета в приложении Какао. Этот метод возвращает пакет, в котором определяется определенный класс. Снова, этот метод главным образом для удобства так, чтобы Вы не сохраняли указатель на NSBundle
возразите, что можно использовать только иногда.
Получение ссылок связать ресурсы
Если у Вас есть ссылка на объект пакета, можно использовать тот объект определить расположение ресурсов в пакете. Какао и Базовая Основа оба обеспечивают различные способы определить местоположение ресурсов в пакете. Кроме того, необходимо понять, как те платформы ищут файлы ресурсов в пакете, чтобы удостовериться, что Вы помещаете файлы в правильные места во время изготовления.
Образец поиска пакета
Пока Вы используете NSBundle
объект или a CFBundleRef
непрозрачный тип для определения местоположения ресурсов код пакета никогда не должен интересоваться тем, как ресурсы получены от пакета. Оба NSBundle
и CFBundleRef
получите надлежащий специфичный для языка ресурс автоматически на основе доступных пользовательских настроек и конфигурации пакета. Однако все еще необходимо поместить все те специфичные для языка ресурсы в пакет, таким образом зная, как они получены, важно.
Интерфейсы программирования пакета следуют за определенным алгоритмом поиска для определения местоположения ресурсов в пакете. Глобальные ресурсы имеют самый высокий приоритет, сопровождаемый областью - и специфичные для языка ресурсы. При рассмотрении области - и специфичные для языка ресурсы, алгоритм принимает во внимание и настройки для текущего пользователя и информацию об области разработки в пакете Info.plist
файл.
Во-первых, пакет определяет который локализация использовать для приложения в целом. Если a .lproj
папка существует для предпочтительного языка, та локализация используется. Иначе, пакет ищет .lproj
папка, соответствующая следующий предпочтительный язык, и т.д., пока, каждый не найден. Если нет никакой локализации для предпочтительного языка, пакет выбирает языковую локализацию разработки.
Тогда пакет ищет ресурс в следующем порядке:
Глобальная переменная (нелокализовала) ресурсы
Специфичные для области локализованные ресурсы (на основе предпочтений области пользователя)
Специфичные для языка локализованные ресурсы (на основе предпочтений языка пользователя)
Ресурсы языка разработки (как указано
CFBundleDevelopmentRegion
в пакетеInfo.plist
файл.)
Поскольку глобальные ресурсы имеют приоритет по специфичным для языка ресурсам, никогда не должно быть и глобальной и локализованной версией данного ресурса. Если глобальная версия ресурса существует, специфичные для языка версии того же ресурса никогда не возвращаются. Причиной этого приоритета является производительность. Если бы локализованные ресурсы искались сначала, то подпрограммы пакета могли бы искать напрасно в нескольких локализованных каталогах ресурса прежде, чем обнаружить глобальный ресурс.
Специфичные для устройства Ресурсы в iOS
В iOS 4.0 и позже, возможно отметить отдельные файлы ресурсов как применимые только на определенном типе устройства. Эта возможность упрощает код, который необходимо записать для Повсеместного применения. Вместо того, чтобы создавать отдельные пути выполнения кода для загрузки одной версии файла ресурсов для iPhone и различной версии файла для iPad можно позволить загружающим пакет подпрограммам выбрать корректный файл. Все, что необходимо сделать, назвать файлы ресурсов соответственно.
Для соединения файла ресурсов с определенным устройством Вы добавляете пользовательскую строку модификатора к ее имени файла. Включение этой строки модификатора приводит к именам файлов со следующим форматом:
<базовое имя> <устройство>.
<filename_extension>
<Базовое имя> строка представляет настоящее имя файла ресурсов. Это также представляет имя, которое Вы используете при доступе к файлу от кода. Точно так же <filename_extension> строка является стандартным расширением файла, используемым для идентификации типа файла. <Устройство> строка является чувствительной к регистру строкой, которая может быть одним из следующих значений:
~ipad
- Ресурс должен быть загружен на устройствах iPad только.~iphone
- Ресурс должен быть загружен на iPhone или устройствах iPod touch только.
Можно применить модификаторы устройства к любому типу файла ресурсов. Например, предположите наличие изображения MyImage.png
. Для указания различных версий изображения для iPad и iPhone Вы создали бы файлы ресурсов с именами MyImage~ipad.png
и MyImage~iphone.png
и включайте их обоих в свой пакет. Для загрузки изображения Вы продолжали бы обращаться к ресурсу как MyImage.png
в Вашем коде и позволяют системе выбрать надлежащую версию, как показано здесь:
UIImage* anImage = [UIImage imageNamed:@"MyImage.png"]; |
На iPhone или устройстве iPod touch, системные нагрузки MyImage~iphone.png
файл ресурсов, в то время как на iPad, это загружается MyImage~ipad.png
файл ресурсов. Если специфичная для устройства версия ресурса не найдена, система отступает к поиску ресурса с исходным именем файла, которое в предыдущем примере было бы названным изображением MyImage.png
.
Получение пути к ресурсу
Для определения местоположения файла ресурсов в пакете необходимо знать имя файла, его типа или комбинации двух. Расширения файла используются для идентификации типа файла; поэтому, важно, чтобы Ваши файлы ресурсов включали надлежащие расширения. При использовании пользовательских подкаталогов в пакете для организации файлов ресурсов, можно ускорить поиск путем обеспечения имени подкаталога, содержащего желаемый файл.
Даже если у Вас нет объекта пакета, можно все еще искать ресурсы в каталогах, пути которых Вы знаете. И Базовая Основа и Какао обеспечивают API для поиска файлов с помощью только находящуюся на пути информацию. (Например, в Какао можно использовать NSFileManager
объект перечислить содержание каталогов и протестировать на существование файлов.) Однако, если Вы планируете получить больше чем один файл ресурсов, это всегда быстрее для использования объекта пакета. Пакет возражает информации о поиске кэша, когда они идут, таким образом, последующие поиски обычно быстрее.
Используя какао для нахождения ресурсов
Если Вы имеете NSBundle
объект, можно использовать следующие методы для нахождения расположения ресурсов в том пакете:
Предположим, что Вы поместили вызванное изображение Seagull.jpg
в основном пакете Вашего приложения. Перечисление 3-8 показывает Вам, как получить путь для этого файла образа от основного пакета приложения.
Перечисление 3-8 , Находящее единственное использование файла ресурсов NSBundle
NSBundle* myBundle = [NSBundle mainBundle]; |
NSString* myImage = [myBundle pathForResource:@"Seagull" ofType:@"jpg"]; |
Если бы Вы хотели искать все ресурсы изображения в своем каталоге ресурса верхнего уровня, вместо того, чтобы искать просто единственный ресурс, то Вы могли использовать pathsForResourcesOfType:inDirectory:
метод или один из его эквивалентов, как показано в Перечислении 3-9
Перечисление 3-9 , Находящее многократное использование ресурсов NSBundle
NSBundle* myBundle = [NSBundle mainBundle]; |
NSArray* myImages = [myBundle pathsForResourcesOfType:@"jpg" |
inDirectory:nil]; |
Используя базовую основу для нахождения ресурсов
Если у Вас есть a CFBundleRef
непрозрачный тип, можно использовать следующие методы для нахождения расположения ресурсов в том пакете:
Предположим, что Вы поместили вызванное изображение Seagull.jpg
в основном пакете Вашего приложения. Перечисление 3-10 показывает Вам, как искать это изображение по имени и тип с помощью Базовой функции Основы CFBundleCopyResourceURL
. В этом случае код ищет файл под названием «Чайка» с типом файла (расширение файла) «jpg» в каталоге ресурса пакета.
Перечисление 3-10 , Находящее единственный ресурс с помощью a CFBundleRef
CFURLRef seagullURL; |
// Look for a resource in the main bundle by name and type. |
seagullURL = CFBundleCopyResourceURL( mainBundle, |
CFSTR("Seagull"), |
CFSTR("jpg"), |
NULL ); |
Предположим, что вместо того, чтобы искать один файл образа, Вы хотели получить имена всех файлов образа в вызванном каталоге BirdImages
. Вы могли загрузить все JPEGs в каталоге с помощью функции CFBundleCopyResourceURLsOfType
, как показано в Перечислении 3-11.
Перечисление 3-11 , Находящее многократные ресурсы с помощью a CFBundleRef
CFArrayRef birdURLs; |
// Find all of the JPEG images in a given directory. |
birdURLs = CFBundleCopyResourceURLsOfType( mainBundle, |
CFSTR("jpg"), |
CFSTR("BirdImages") ); |
Открываясь и Используя файлы ресурсов
Как только у Вас есть ссылка на файл ресурсов, можно загрузить его содержание и использовать его в приложении. Шаги, которые необходимо предпринять, чтобы загрузить и использовать файлы ресурсов, зависят от типа ресурса, и как таковой не охвачен в этом документе. Для получения дальнейшей информации о загрузке и использовании ресурсов, см. Руководство по программированию Ресурса.
Нахождение других файлов в пакете
С допустимым объектом пакета можно получить путь к каталогу пакета верхнего уровня, а также пути ко многим его подкаталогам. Используя доступные интерфейсы для получения путей к каталогам изолирует код от необходимости знать точную структуру пакета или его расположения в системе. Это также позволяет Вам использовать тот же код различных платформ. Например, Вы могли использовать тот же код для получения ресурсов из приложения для iOS или приложения Mac, имеющих различные структуры пакета.
Для получения пути к каталогу пакета верхнего уровня с помощью Какао Вы используете bundlePath
метод соответствия NSBundle
объект. Можно также использовать builtInPlugInsPath
, resourcePath
, sharedFrameworksPath
, и sharedSupportPath
методы для получения путей для ключевых подкаталогов пакета. Эти методы информация об обратном тракте с помощью NSString
объект, который можно передать непосредственно большинство другому NSBundle
методы или преобразовывают в NSURL
возразите по мере необходимости.
Базовая Основа также определяет функции для получения нескольких различных внутренних каталогов пакета. Для получения пути самого пакета можно использовать CFBundleCopyBundleURL
функция. Можно также использовать CFBundleCopyBuiltInPlugInsURL
, CFBundleCopyResourcesDirectoryURL
, CFBundleCopySharedFrameworksURL
, и CFBundleCopySupportFilesDirectoryURL
функции для получения расположений ключевых подкаталогов пакета. Базовая Основа всегда возвращает пути пакета как a CFURLRef
непрозрачный тип. Можно использовать этот тип для выдержки a CFStringRef
введите это, можно тогда передать другим Базовым подпрограммам Основы.
Получение данных пакета Info.plist
Один файл, который должен содержать каждый пакет, является информационным списком свойств (Info.plist
) файл. Этот файл является основанным на XML текстовым файлом, содержащим определенные типы пар ключ/значение. Эти пары ключ/значение указывают информацию о пакете, таком как его Строка идентификатора, номер версии, область разработки, вводят, и другие важные свойства. (См. Инструкции по Конфигурации Во время выполнения для списка ключей, которые можно включать в этот файл.) Пакеты могут также включать другие типы данных конфигурации, главным образом организованных в основанных на XML списках свойств.
NSBundle
класс обеспечивает objectForInfoDictionaryKey:
и infoDictionary
методы для получения информации от Info.plist
файл. objectForInfoDictionaryKey:
метод возвращает локализованное значение для ключа и является предпочтительным методом вызвать. infoDictionary
метод возвращается NSDictionary
со всеми ключами от списка свойств; однако, это не возвращает локализованных значений для этих ключей. Для получения дополнительной информации посмотрите Ссылку класса NSBundle.
Базовая Основа также предлагает функции для получения определенных частей данных от информационного файла списка свойств пакета, включая Строку идентификатора пакета, версию и область разработки. Можно получить локализованное значение для ключа с помощью CFBundleGetValueForInfoDictionaryKey
функция. Можно также получить весь словарь нелокализованного ключевого использования CFBundleGetInfoDictionary
. Для получения дополнительной информации об этих и связанных функциях, см. Ссылку CFBundle.
Перечисление 3-12 демонстрирует, как получить номер версии пакета от информационного списка свойств с помощью Базовых функций Основы. Хотя значение в информационном списке свойств может быть записано как строка, например «2.1.0b7», значение возвращается как длинное целое без знака.
Перечисление 3-12 Получая версию пакета
// This is the ‘vers’ resource style value for 1.0.0 |
#define kMyBundleVersion1 0x01008000 |
UInt32 bundleVersion; |
// Look for the bundle’s version number. |
bundleVersion = CFBundleGetVersionNumber( mainBundle ); |
// Check the bundle version for compatibility with the app. |
if (bundleVersion < kMyBundleVersion1) |
return (kErrorFatalBundleTooOld); |
Перечисление 3-13 показывает Вам, как получить произвольные значения от информационного списка свойств с помощью CFBundleGetInfoDictionary
функция. Получающийся информационный список свойств является экземпляром стандартного Базового типа Основы CFDictionaryRef
. Для получения дополнительной информации о получении информации из Базового словаря Основы, см. Ссылку CFDictionary.
Перечисление 3-13 , Получающее информацию от информационного списка свойств пакета
CFDictionaryRef bundleInfoDict; |
CFStringRef myPropertyString; |
// Get an instance of the non-localized keys. |
bundleInfoDict = CFBundleGetInfoDictionary( myBundle ); |
// If we succeeded, look for our property. |
if ( bundleInfoDict != NULL ) { |
myPropertyString = CFDictionaryGetValue( bundleInfoDict, |
CFSTR("MyPropertyKey") ); |
} |
Также возможно получить экземпляр информационного словаря пакета без объекта пакета. Чтобы сделать это, Вы используете любого Базовая функция Основы CFBundleCopyInfoDictionaryInDirectory
или Какао NSDictionary
класс. Это может быть полезно для поиска информационных списков свойств ряда пакетов без первых объектов пакета создания.
Исполняемый код загрузки и разгрузки
Ключ к загружающемуся коду от внешнего пакета находит надлежащую точку входа в исполняемый файл пакета. Как с другими сменными схемами, это требует некоторой координации между разработчиком приложений и сменным разработчиком. Можно опубликовать пользовательский API для пакетов, чтобы реализовать или определить формальный сменный интерфейс. Или в случае, как только у Вас есть надлежащий пакет или в плагин, Вы используете NSBundle
класс (или CFBundleRef
непрозрачный тип) для доступа к функциям или классам, реализованным внешним кодом.
Для получения дополнительной информации о коде загрузки и разгрузки посмотрите, что Код Загружает Темы Программирования.
Загрузка функций
Если Вы работаете в C, C++, или даже в Objective C, можно опубликовать интерфейс как ряд символов на базе С, таких как указатели функции и глобальные переменные. Используя Базовые функции Основы, можно загрузить ссылки на те символы от исполняемого файла пакета.
Можно получить символы с помощью любой из нескольких функций. Для получения указателей функции вызовите также CFBundleGetFunctionPointerForName
или CFBundleGetFunctionPointersForNames
. Для получения указателя на глобальную переменную вызвать CFBundleGetDataPointerForName
или CFBundleGetDataPointersForNames
. Например, предположите, что загружаемый пакет определяет функцию, показанную в Перечислении 3-14.
Перечисление 3-14 пример функционирует для загружаемого пакета
// Add one to the incoming value and return it. |
long addOne(short number) |
{ |
return ( (long)number + 1 ); |
} |
Данный a CFBundleRef
непрозрачный тип, необходимо было бы искать желаемую функцию, прежде чем Вы могли использовать его в своем коде. Перечисление 3-15 показывает фрагмент кода, иллюстрирующий этот процесс. В этом примере, myBundle
переменная является a CFBundleRef
непрозрачный тип, указывающий на пакет.
Перечисление 3-15 , Находящее функцию в загружаемом пакете
// Function pointer. |
AddOneFunctionPtr addOne = NULL; |
// Value returned from the loaded function. |
long result = 0; |
// Get a pointer to the function. |
addOne = (void*)CFBundleGetFunctionPointerForName( |
myBundle, CFSTR("addOne") ); |
// If the function was found, call it with a test value. |
if (addOne) |
{ |
// This should add 1 to whatever was passed in |
result = addOne ( 23 ); |
} |
Загрузка классов Objective C
Если Вы пишете приложение Какао, можно загрузить код для всего класса с помощью методов NSBundle
. NSBundle
методы для загрузки класса для использования с классами Objective C только и не могут использоваться для загрузки классов, записанных в C++ или других объектно-ориентированных языках.
Если загружаемый пакет определяет основной класс, можно загрузить его с помощью principalClass
метод NSBundle
. principalClass
метод использует NSPrincipalClass
ключ пакета Info.plist
файл, чтобы идентифицировать и загрузить желаемый класс. Используя основной класс улучшает потребность согласиться с определенными соглашениями о присвоении имен для внешних классов, вместо этого позволяя Вам фокусироваться на поведении тех интерфейсов. Например, Вы могли бы использовать экземпляр основного класса как фабрика для создания других соответствующих объектов.
Если Вы хотите загрузить произвольный класс из загружаемого пакета, вызовите classNamed:
метод NSBundle
. Этот метод ищет пакет класс, соответствующий имя, которое Вы указываете. Если класс существует в пакете, метод возвращает соответствие Class
объект, который можно тогда использовать для создания экземпляров класса.
Перечисление 3-16 показывает Вам выборочный метод для загрузки основного класса пакета.
Перечисление 3-16 , Загружающее основной класс пакета
- (void)loadBundle:(NSString*)bundlePath |
{ |
Class exampleClass; |
id newInstance; |
NSBundle *bundleToLoad = [NSBundle bundleWithPath:bundlePath]; |
if (exampleClass = [bundleToLoad principalClass]) |
{ |
newInstance = [[exampleClass alloc] init]; |
// [newInstance doSomething]; |
} |
} |
Для получения дополнительной информации о методах NSBundle
класс, см. Ссылку класса NSBundle.
Разгрузка пакетов
В OS X v10.5 и позже, можно разгрузить код, связанный с NSBundle
объект с помощью unload
метод. Вы могли бы использовать этот метод для высвобождения памяти в приложении путем удаления плагинов или других загружаемых пакетов, в которых Вы больше не нуждаетесь.
При использовании Базовой Основы для загрузки пакета, можно использовать CFBundleUnloadExecutable
функция для разгрузки его. Если Ваш пакет мог бы быть разгружен, необходимо гарантировать, что строковые константы обрабатываются правильно путем установки надлежащего флага компилятора.
При компиляции пакета с минимальной целью развертывания OS X v10.2 (или позже), компилятор автоматически переключается на генерацию строк, которые являются действительно постоянными в ответ на CFSTR("...")
. Если Вы компилируете с флагом, компилятор также генерирует эти постоянные строки -fconstant-cfstrings
. Постоянные строки обладают многими преимуществами и должны использоваться, если это возможно, однако при ссылке на постоянные строки после того, как исполнимая программа, содержащая их, будет разгружена, ссылки будут недопустимы и вызовут катастрофический отказ. Даже если строки были сохранены, например, в результате того, чтобы быть помещенным в структуры данных, сохраненные непосредственно, и, в некоторых случаях, даже скопированный, это могло бы произойти. Вместо того, чтобы пытаться удостовериться, все такие ссылки очищены в, разгружают время (и некоторые ссылки могли бы быть созданы в библиотеках, делая их трудно для отслеживания), лучше компилировать незагружаемые пакеты с флагом -fno-constant-cfstrings
.