Объектные спецификаторы
Объектный спецификатор определяет местоположение scriptable объекта в иерархии вместимости приложения. Сценарии какао используют объектные спецификаторы, чтобы найти объекты в Вашем приложении при выполнении команды сценария и возвратить требуемую информацию сценарием. В этой главе описываются, как Какао, пишущее сценарий использования, возражает спецификаторам и как Ваше приложение обеспечивает объектные спецификаторы для своих scriptable объектов.
Обзор объектных спецификаторов
Сценарий AppleScript содержит операторы, управляющие объектами в объектной модели AppleScript приложения. Часть оператора сценария, идентифицирующего объект, такой как fourth word
, вызывается ссылкой. Ссылка редко происходит в изоляции. Обычно оператор сценария состоит из серии ссылок, которым предшествует команда и обычно подключенных друг к другу in
или of
, такой как get the fourth word in the third paragraph of document "Quarterly Report"
.
Событие Apple инкапсулирует работу, указанную оператором сценария, и поставляет ее приложению. Для событий Apple, соответствующих командам, определенным в sdef файле приложения, сценарии Какао преобразовывают событие Apple в команду сценария, содержащую всю информацию, необходимую для выполнения работы.
Для описания объектов, указанных ссылкой, команда использует объектные спецификаторы. Где оператор сценария идентифицирует объект в объектной модели AppleScript, объектный спецификатор идентифицирует соответствующий объект в самом приложении. Когда приложение должно возвратить объект сценарию выполнения вызова, Какао, пишущее сценарий также, использует объектный спецификатор, предоставленный Вашим приложением, для идентификации объекта.
Существует не всегда взаимно-однозначное соответствие между объектами AppleScript и объектами в реализации Вашего приложения. Например, a character
объект в сценарии не имеет соответствия character
объект в приложении.
Объектные спецификаторы и KVC
Сценарии какао полагаются на кодирование значения ключа (KVC) при оценке объектных спецификаторов. Когда приложение сначала должно работать с scriptability информацией, Какао, пишущее сценарий информации о загрузках от sdef файла приложения в глобальный экземпляр NSScriptSuiteRegistry
. В то время это регистрирует описания класса для Ваших scriptable классов. В результате Какао и Ваше приложение могут получить информацию об описании класса сценария, включая ключи, о scriptable классах для использования с объектными спецификаторами.
Для получения дополнительной информации посмотрите Загрузку информация о Scriptability.
Когда реализовать объектный метод спецификатора
Любой класс в Вашем приложении, которое является частью иерархии вместимости для Вашей поддержки scriptability, наиболее вероятно потребует объектного метода спецификатора. Когда оператор сценария предназначается для Вашего приложения, приложение, возможно, должно возвратить ответ. Например, результат a get
команда часто является объектом или списком объектов. Когда Какао возвращает эти объекты в событии Apple ответа, оно не возвращает указатели на объекты Objective C, оно возвращает объектные спецификаторы, определяющие местоположение scriptable объектов в иерархии вместимости. Как часть создания этих спецификаторов, Какао обращается к Вашим scriptable объектам предоставить спецификаторы для себя.
Вы обеспечиваете объектный спецификатор для scriptable класса путем реализации objectSpecifier
метод. Тот метод определяется в NSScriptObjectSpecifiers
(отметьте запаздывание «s»), категория на NSObject
это реализует просто возвращающуюся версию nil
.
Об объектных классах спецификатора
objectSpecifier
метод возвращает экземпляр одного из классов, перечисленных в Таблице 6-1, которые являются подклассами NSScriptObjectSpecifier
. Классы такой как NSNameSpecifier
и NSUniqueIDSpecifier
представляйте стандартные ссылочные формы AppleScript, таким образом, Вы не должны должны быть разделять их на подклассы. Вы выбираете лучшую версию для объекта, который необходимо указать — см. Инструкции по Интерфейсу Сценариев для руководства. Например, если объект имеет уникальное имя или уникальный идентификатор, используйте соответствующий тип спецификатора. Для безымянного объекта без ID, такого как прямоугольник или абзац текста, можно хотеть возвратить индексный спецификатор.
Большинство подклассов NSScriptObjectSpecifier
имейте определенный инициализатор, который необходимо использовать.
Большинство методов инициализатора для объектного класса спецификатора включает следующие параметры:
(NSScriptClassDescription *)classDescription
Здесь Вы предоставляете описание класса для контейнерного класса указанного объекта. Необходимо всегда предоставлять описание класса для спецификатора.
Если у Вас уже есть объектный спецификатор для контейнера, можно получить описание класса для того контейнерного объекта с помощью
NSScriptObjectSpecifier
методkeyClassDescription
, как показано в Перечислении 6-1.Когда можно получить класс контейнерного объекта (например, путем вызова
[NSApp class]
), можно использоватьclassDescriptionForClass
метод для определения контейнерного описания, как показано в Перечислении 6-2. Если у Вас есть экземпляр класса контейнера, можно вместо этого использоватьNSObject
метод экземпляраclassDescription
получить контейнерное описание.(NSScriptObjectSpecifier *)specifier
Здесь Вы предоставляете объектный спецификатор для родительского контейнера указанного объекта. Вы обычно получаете его путем вызова
objectSpecifier
метод содержания объекта.Объект, не имеющий никакого контейнерного спецификатора, известен как спецификатор верхнего уровня. В большинстве случаев спецификатор верхнего уровня является самим приложением. Можно указать спецификатор верхнего уровня путем передачи
nil
для этого параметра. (Который является единственным временем, которое можно передатьnil
для контейнерного спецификатора, и даже тогда необходимо указать описание контейнерного класса.)(NSString *)key
Здесь Вы предоставляете ключ, говорящий родительский контейнер, как найти указанный объект. Ключ, который Вы передаете, основывается на информации, предоставленной в Вашем sdef файле. Например, Эскиз определяет
"graphics"
ключ для идентификации графического массива в документе Эскиза. (Эскиз фактически определяет исключительное"graphic"
как элементdocument
класс, но сценарии Какао применяет свои стандартные правила, описанный в Обеспечивают Ключи для Кодирования Значения ключа, для преобразования этого ключа в строку"graphics"
.)
Для аннотируемого примера objectSpecifier
метод, посмотрите Объектный Метод Спецификатора для Прямоугольника в Эскизе.
Более внимательное рассмотрение в объектном спецификаторе
Рассмотрите схему объектной модели и иерархии вместимости для примера приложения Эскиза, показанного на рисунке 6-1. Левая сторона этой иллюстрации показывает scriptable объекты Эскиза, правая сторона соответствующая иерархия вместимости приложения. Для оператора сценария, идентифицирующего a rectangle
возразите слева, сценарии Какао предоставляют объектный спецификатор, определяющий местоположение прямоугольника и его содержания документа в иерархии вместимости справа.
Каждый объектный спецификатор содержит ссылку на свое содержание объекта, позволяющего объектным спецификаторам представлять объекты, которые могут быть глубоко вложены в иерархии объектов. Наиболее удаленный контейнер, представленный нулевым спецификатором объекта, обычно application
объект, несмотря на то, что это может быть объектный спецификатор, вовлеченный в a whose
пункт (NSWhoseSpecifier
) или контейнер для оценки диапазона.
Рисунок 6-2 показывает спецификаторы вложенного объекта для оператора first rectangle in document "SketchDocOne"
:
Вот то, как интерпретировать информацию в этом числе:
Индексный спецификатор указывает первый прямоугольник, который является объектом класса
SKTRectangle
. Спецификатор имеет эти компоненты:Индекс для указанного объекта, в этом примере имеющего значение
0
.Это - основанный на нуле индекс указанного прямоугольника в его содержании массива. Поскольку графические массивы Эскиза могут содержать другие виды графики, индекс для первого прямоугольника будет не всегда иметь значение
0
— например, если бы предшествуется четырьмя круговой графикой, индекс имел бы значение4
.Ключ, указывающий набор для указанного объекта, в этом примере имеющего значение
"graphics"
.Графический массив является набором для индексируемого объекта. Ключ соответствует информацию, предоставленную Вашим sdef и сделанную доступный в запущенном приложении, как описано в Объектных Спецификаторах и KVC.
Контейнерная ссылка, указывающая родителя для этого объектного спецификатора. В этом примере контейнер является объектным спецификатором для документа
"SketchDocOne"
.
Спецификатор имени указывает документ, содержащий первый прямоугольник, который является объектом класса
SKTDrawDocument
. Спецификатор имеет эти компоненты:Имя для указанного объекта, в этом примере имеющего значение
"SketchDocOne"
.Ключ, указывающий набор для указанного объекта, в этом примере имеющего значение
"orderedDocuments"
.Упорядоченный массив приложения документов является набором для именованного документа, хотя в этом случае, порядок неважен.
Контейнерная ссылка, указывающая родителя для этого объектного спецификатора. В этом примере ссылка
nil
, указание, что массив документов содержитсяapplication
объект.
Оператор сценария, и таким образом объектный спецификатор, могут указать объекты, в настоящее время не существующие в приложении, вызывая состояние ошибки, когда выполняется сценарий. Например, указанный документ может не существовать, или он может не содержать указанную диаграмму. Код в классе команды должен проверить на и быть подготовлен обработать условия распространенной ошибки. (Проверку не считают подходящей для методов получателя KVC и методов установщика.)
Оценка вложенных спецификаторов
Когда сценарии Какао подготавливают команду сценария к сценарию, содержащему ссылку, они преобразовывают ссылку во вложенную серию объектных спецификаторов, таких как те показанные на рисунке 6-2. Это упаковывает эти спецификаторы вложенного объекта как получатель команды (или в некоторых случаях как параметр команды). Когда команда выполняется, приложение оценивает объектные спецификаторы в своем собственном контексте для обнаружения указанных объектов.
Оценка запускается со спецификатора верхнего уровня и продолжает вниз цепочку объектных спецификаторов, оценивая и разрешая каждого, пока не определяются идентификационные данные заключительного, вложенного дочернего объекта. Этот объект является получателем (или получателями) команды или одного из параметров команды. Кодирование значения ключа используется в качестве стандартного механизма для оценки. Объектный спецификатор запрашивает свой оцененный контейнер для значения ключа, связанного с объектным спецификатором.
Оценка объектных спецификаторов описана более подробно в Командах Сценария и Объектных Спецификаторах.
Классы спецификатора объекта какао
AppleScript распознает много типов ссылок. Для стандартных ссылочных форм Какао определяет подклассы абстрактного класса NSScriptObjectSpecifier
. Эти классы показаны в Таблице 6-1. Каждый из этих объектных классов спецификатора имеет дело с идентификацией объектов в наборах (NSArray
объекты).
Эти классы необычны в этом, они обеспечивают один из нескольких примеров, где Ваше приложение обычно создает экземпляры сценариев классов, определенных Какао. Вы делаете это в объектных методах спецификатора для Ваших scriptable классов. Для получения дополнительной информации об этих и связанных классах см. также Таблицу 9-2.
Маловероятно, что необходимо будет разделить любой на подклассы из этих классов, поскольку они уже покрывают стандартный набор допустимых ссылочных форм AppleScript. Однако, если действительно необходимо создать подкласс, необходимо переопределить примитивный метод indicesOfObjectsByEvaluatingWithContainer:count:
возвратить индексы элементам в контейнере, значения которого являются соответствующими ключу дочернего спецификатора. Кроме того, Вы, возможно, должны объявить любые специальные переменные экземпляра и реализовать инициализатор, вызывающий определяемый инициализатор его суперкласса, initWithContainerClassDescription:containerSpecifier:key:
, и инициализирует эти переменные.
В дополнение к конкретным подклассам NSScriptObjectSpecifier
показанный в Таблице 6-1, Какао обеспечивает другие классы, помогающие классам объектного спецификатора в оценке. Экземпляры этих классов помогают указать относительную позицию и представлять Булевы и логические выражения, в которые вовлечены объектные спецификаторы.
Оператор сценария может также содержать ссылки фильтра, идентифицирующие объекты в контейнерах на основе условий, указанных в булевых выражениях. Эти выражения могут быть соединены логическими операторами (AND, OR, НЕ) и возвратить надлежащее true
или false
значение. Ссылки фильтра начинаются со слов whose
или where
, как в get words where color is blue or color is red
и rectangles whose x position is greater than 45
. Эти ссылки могут содержать фразы такой как is
, is equal to
или is greater than
, а также их символьные эквиваленты (такой как =
и >
).
Экземпляры NSWhoseSpecifier
класс представляет ссылочные формы фильтра в Какао. Эти экземпляры содержат «тестовую» переменную экземпляра, которая является NSScriptWhoseTest
объект.
Для получения информации об этих и связанных классах посмотрите Объектные Спецификаторы, Логические Тесты и Связанные Категории.
Реализация объектного метода спецификатора
Следующие разделы обеспечивают примеры того, как реализовать объектный спецификатор, определенный NSScriptObjectSpecifiers
.
Объектный метод спецификатора для прямоугольника в эскизе
Перечисление 6-1 показывает, как пример приложения Эскиза (доступный от Apple) реализует objectSpecifier
метод для SKTGraphic
класс.
Перечисление 6-1 объектный метод спецификатора для прямоугольника
- (NSScriptObjectSpecifier *)objectSpecifier{ |
NSArray *graphics = [[self document] graphics];// 1 |
unsigned index = [graphics indexOfObjectIdenticalTo:self];// 2 |
if (index != NSNotFound) { |
NSScriptObjectSpecifier *containerRef = [[self document] objectSpecifier];// 3 |
return [[[NSIndexSpecifier allocWithZone:[self zone]] |
initWithContainerClassDescription:[containerRef keyClassDescription] |
containerSpecifier:containerRef key:@"graphics" index:index] autorelease];// 4 |
} else { |
return nil;// 5 |
} |
} |
Вот описание того, как этот метод обеспечивает объектный спецификатор для графического объекта. Возвращенный спецификатор состоит из индексного спецификатора для диаграммы в ее контейнере и контейнерного спецификатора для документа, содержащего массив графики:
Из его документа это получает массив графики и определяет индекс графического получения, если это содержится в массиве.
Это получает объектный спецификатор документа, содержащего диаграмму.
Эскиз определяет
SKTDrawDocument
класс как подклассNSDocument
. Объектный метод спецификатора дляNSDocument
возвращает экземплярNSNameSpecifier
это идентифицирует документ по имени в массиве приложения упорядоченных документов.Это создает и инициализирует индексный спецификатор (тип
NSIndexSpecifier
) для графического получения и возвраты это.Спецификатор определяет местоположение диаграммы индексом в графике в ее документе. Несмотря на то, что сценарий AppleScript просит индексируемые элементы, как будто они на основе одни, этот индексный спецификатор, определяющий местоположение объектов в массиве, соответствующих указанным элементам, работам с основанными на нуле значениями. Для получения информации о других параметрах займитесь Объектными Классами Спецификатора.
Указание объекта приложения как контейнер
Для указания объекта приложения как контейнер верхнего уровня для спецификатора можно использовать код как следующий. Этот отрывок является частью класса документа и получает объектный спецификатор для документа по имени (а не индексом, который может стать недопустимым если документ, упорядочив изменения):
Перечисление 6-2 , Указывающее приложение как контейнер
NSScriptClassDescription *containerClassDesc = (NSScriptClassDescription *) |
[NSScriptClassDescription classDescriptionForClass:[NSApp class]];// 1 |
return [[[NSNameSpecifier alloc] |
initWithContainerClassDescription:containerClassDesc |
containerSpecifier:nil key:@"orderedDocuments" |
name:[self lastComponentOfFileName]] autorelease];// 2 |
Вот описание того, что делает этот фрагмент кода:
Приложение является контейнером для списка упорядоченных документов, таким образом, этот код сначала получает описание класса из глобального объекта приложения,
NSApp
. (Вы никогда не передаетеnil
для описания класса.)Это тогда создает и возвращает автовыпущенный объектный спецификатор типа
NSNameSpecifier
, передачаnil
дляcontainerSpecifier
параметр для указания контейнера верхнего уровня, приложения. (Это - единственный случай, в котором можно передатьnil
для контейнера.)Это вызывает
NSDocument
методlastComponentOfFileName
получить имя документа и использования это для построения объекта спецификатора имени.
Реализация метода для оценки объектных спецификаторов
Контейнерные классы, хотящие оценить определенные объектные спецификаторы самостоятельно, должны реализовать indicesOfObjectsByEvaluatingObjectSpecifier:
метод, определенный NSScriptObjectSpecifiers
(категория на NSObject
). Например, Вы могли бы принять решение реализовать этот метод при нахождении этого whose
оценка пункта является слишком медленной, и Вы хотите сделать свою собственную оценку для ускорения ее (хотя для большинства приложений, производительности значения по умолчанию whose
механизм должен быть достаточным).
Если возвращается этот метод nil
, объектный метод спецификатора для класса делает свою собственную оценку. Если этот метод возвращает массив, объектный спецификатор использует NSNumber
объекты в массиве как индексы указанных объектов.
Поэтому при реализации этого метода и когда Вы оцениваете спецификатор нет никаких объектов, соответствующих, возвращающих пустой массив, нет nil
. При нахождении только одного объекта Вы возвращаете его индекс в массиве. Возврат массива с единственным индексом, где индекс –1, интерпретируется для значения всего соответствия объектов.
Приложение Эскиза реализует этот метод в своем классе документа, как показано в Перечислении 6-3. Это позволяет Эскизу непосредственно обрабатывать некоторый диапазон и относительные спецификаторы для графики, таким образом, это может поддерживать операторы сценария такой как graphics from circle 3 to circle 5
, circles from graphic 1 to graphic 10
, или circle before rectangle 3
.
Перечисление 6-3 indicesOfObjectsByEvaluatingObjectSpecifier: метод из Эскиза
Вот описание того, как работает этот метод:
Если переданный спецификатор является спецификатором диапазона, он возвращает результат вызова другого метода Эскиза для оценки спецификатора.
Метод
indicesOfObjectsByEvaluatingRangeSpecifier:
позволяет более гибким спецификаторам диапазона использоваться с различными графическими ключами aSKTDrawDocument
.Можно исследовать этот метод в Эскизе. Описание его полностью выходит за рамки этого обсуждения.
Если переданный спецификатор является относительным спецификатором, он возвращает результат вызова другого метода Эскиза для оценки спецификатора.
Метод
indicesOfObjectsByEvaluatingRelativeSpecifier:
позволяет более гибким относительным спецификаторам использоваться.Снова, этот метод доступен в Эскизе, но выходит за рамки этого обсуждения.
Для любого другого типа спецификатора, этот метод возвраты
nil
так, чтобы объектная оценка спецификатора по умолчанию имела место.
Неявно указанные подконтейнеры
Сценарии какао предоставляют поддержку для неявно указанных подконтейнеров. Неявно указанный подконтейнер является контейнером объекта, который может быть указан в сценарии AppleScript контекстом, а не прямой ссылкой. Без этой функции сценарий должен был бы полностью указать путь к слову в, например, документ TextEdit:
fourth word of text of front document
Можно сделать жизнь проще для сценаристов, использующих приложение путем избавления их от необходимости писать полные ссылки на объекты в ситуациях, где может быть безопасно принята часть ссылки. Например, следующее было бы более простым, но разумным способом относиться к тому же слову, так как текст является очевидным контейнером слов в документе:
fourth word of front document
Т.е. можно позволить of text
быть неявно указанным контекстом, вместо явно указанного в сценарии.
Для поддержки неявно указанного подконтейнера Вы добавляете a contents
элемент к class
элемент для содержания класса в Вашем sdef файле. contents
элемент указывает, что сценарист может получить содержание объекта этого типа класса, не указывая контейнер, содержащий содержание.
Например, предположите, что Ваше приложение имеет класс документа, MyTextDocument
, это обрабатывает текст с экземпляром NSTextStorage
класс. NSTextStorage
поддержки scriptability для слов, абзацев и других текстовых элементов перечислены в Таблице 3-2.
Ваше приложение может превратить текстовый экземпляр ресурса хранения в неявно указанный подконтейнер, так, чтобы пользователь не должен был указывать его в сценарии, но мог указать просто документ, как в выборке, показанной выше. Для этого Вы добавляете a contents
запись для document
класс поддержки, как показано в Перечислении 6-4. Это contents
элемент указывает это для сценария для доступа к связанному с текстом содержанию a document
объект, это может просто указать document
объект, не имея необходимость указывать контейнер в объекте.
MyTextDocument
класс реализовал бы средства доступа, соответствующие ключ Cocoa, определенный в sdef: т.е. contents
и setContents:
. Для идеи того, на что могли бы быть похожими эти средства доступа, посмотрите столь же именованные средства доступа для класса текстовой области (SKTTextArea
) в приложении Эскиза.
Определение класса перечисления 6-4 для текстового документа, содержа элемент содержания
<class name="document" code="docu" |
description="A text document."> |
<cocoa class="MyTextDocument"/> |
<contents name="text contents" code="TeCo" type="rich text" |
description="The text of the document."> |
<cocoa key="contents"/> |
</contents> |
</class> |
Когда Вы предоставляете a contents
запись, надлежащее NSPropertySpecifier
когда ссылка с помощью того контейнерного класса иначе была бы недопустима, будет вставлен в объектную цепочку включения спецификатора.