Не удается заставить пример Apple SimpleScripting работать при использовании NSApplicationDelegate

Я пытаюсь написать тривиальное приложение Objective-C: я просто хочу приложение, которое будет отображать слово в строке состояния и позволяет обновлять слово через AppleScript. Честно говоря, я мало знаю об AppleScript и ничего о Objective-C. Но это не может быть так сложно, потому что мне потребовалось всего 2 часа, чтобы получить приложение menubar, которое имеет пункты меню и отвечает на основные команды AppleScript, такие как "выход", так что я на 95%. К сожалению, я потратил следующие 6 часов, пытаясь найти способ дать этому приложению простое свойство, которое я могу получить и установить с помощью AppleScript.

Вот мой код.h:

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate> {
    NSWindow *window;
    IBOutlet NSMenu *statusMenu;
    NSStatusItem *statusItem;
}
@property (assign) IBOutlet NSWindow *window;
- (NSString*) foobaz;
@end

foobaz метод, который я использовал, чтобы попытаться сделать читаемое свойство (*window является частью шаблона, который мне дал XCode, и не имеет отношения к данной проблеме). Вот мой файл.sdef:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary xmlns:xi="http://www.w3.org/2003/XInclude">
  <xi:include
    href="file:///System/Library/ScriptingDefinitions/CocoaStandard.sdef"
    xpointer="xpointer(/dictionary/suite)"/>
  <suite name="StatusMenuApp suite" code="smas"
    description="StatusMenuApp specific classes.">
    <class name="application" code="smaa" inhereits="application"
      description="Application object.">
      <cocoa class="AppDelegate"/>
      <property name="foobaz" code="smas" type="text" access="r"/>
    </class>
  </suite>
</dictionary>

Итак, я настроил его так же, как пример SimpleScripting от Apple, здесь: https://developer.apple.com/library/mac/

Тем не менее, я попытался запустить это в редакторе сценариев:

tell application "StautsMenuApp"
    properties
end tell

И я просто получаю список основных свойств, без упоминания foobaz в отличие от примера Apple, в котором пользовательское свойство появляется вместе с основными свойствами, когда я его запускаю.

Я чувствую, что перепробовал сотни вариантов и прочитал сотни примеров, но ничего не смог сделать. Любая помощь приветствуется.

2 ответа

Есть много проблем с вашим файлом SDEF.

  1. Хотя это не является серьезной проблемой, при определении ваших собственных "типов" (OSType коды), все строчные буквы исторически зарезервированы для Apple. Итак, вы должны сделать что-то вроде 'Smas' или же 'sMas' но нет 'smas',

  2. Это может быть опечатка здесь в веб-браузере, но вы ошиблись inhereits в соответствии <class name="application" code="smaa" inhereits="application"..., Важно, чтобы написание было правильным, чтобы вы могли правильно "расширить" базовый AppleScript application класс со своими собственными дополнительными свойствами. Это может быть причиной того, что вы видите только свойства приложения по умолчанию в AppleScript Editor. (Хотя исправление орфографии само по себе может позволить вещи работать, есть и другие исправления, которые вы должны сделать).

  3. Вы пытаетесь указать, что класс Какао для вашего "расширенного" application AppleScript класс AppDelegate, но это проблематично, потому что AppDelegate не наследуется от NSApplication как указано в примере Apple.Sdef, скорее, он наследует от простого старого NSObject,

Прежде чем перейти к тому, как мне переписать SDEF, я рассмотрю, в чем заключается основная идея того, как работает пример SDEF от Apple для добавления пользовательских свойств в AppleScript по умолчанию. application учебный класс. AppleScript application класс соответствует NSApplication Класс какао. Когда вы запускаете приложение, OS X создает экземпляр NSApplication (или его подкласс, как указано NSPrincipalClass запись в файле Info.plist приложения). Этот экземпляр управляет приложением. В Какао есть 2 возможных способа добавить дополнительные свойства AppleScript к существующему NSApplication класс: 1) создать собственный подкласс NSApplication которые содержат дополнительные свойства или 2) использовать категорию Objective-C для расширения существующих NSApplication класс как есть. (В Какао категории Objective C - способ добавить дополнительную функциональность к существующему классу без потенциальных сложностей, которые вводит подклассирование). Apple, SimpleScripting В примере используется последний подход (категории Objective C) для добавления дополнительной функциональности.

Ниже я хотел бы переписать SDEF.

SimpleScriptingAppDelegate.sdef:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary xmlns:xi="http://www.w3.org/2003/XInclude">
    <xi:include
    href="file:///System/Library/ScriptingDefinitions/CocoaStandard.sdef"
    xpointer="xpointer(/dictionary/suite)"/>
    <suite name="StatusMenuApp suite" code="SSAD"
                 description="StatusMenuApp-specific classes.">
        <class name="application" code="capp" inherits="application"
                                 description="Application object.">
            <cocoa class="NSApplication"/>
            <property name="foobaz" code="Foob"
                description="Description of the foobaz property." type="text">
                <cocoa key="foobaz"/>
            </property>
        </class>
    </suite>
</dictionary>

Вы заметите, что я указал, что я создаю собственный AppleScript application класс, который наследуется от стандартного AppleScript application учебный класс. Я указал, что класс Какао для этого обычая application является NSApplication, Я добавил собственное свойство AppleScript, имя которого foobaz и чей тип text, (AppleScript text класс будет соответствовать Какао NSString учебный класс). Также важно то, что я указал, что ключ Какао для доступа к этому пользовательскому свойству foobaz, Этот "ключ какао" указывает имя метода Objective C, который будет использоваться для предоставления значения для свойства. Определенная выше конфигурация указывает, что foobaz свойство можно получить, позвонив foobaz метод на общем экземпляре NSApplication объект.

Чтобы реализовать это в аспекте Какао, я определил (MDScriptingAdditions) категория на NSApplication как показано ниже:

MDNSApplicationScriptingAdditions.h:

@interface NSApplication (MDScriptingAdditions)

- (NSString *)foobaz;
- (void)setFoobaz:(NSString *)aFoobaz;

@end

MDNSApplicationScriptingAdditions.m:

#import "MDNSApplicationScriptingAdditions.h"
#import "AppDelegate.h"

@implementation NSApplication (MDScriptingAdditions)

- (NSString *)foobaz {
    return [(AppDelegate *)[NSApp delegate] foobaz];
}

- (void)setFoobaz:(NSString *)aFoobaz {
    return [(AppDelegate *)[NSApp delegate] setFoobaz:aFoobaz];
}
@end

Вы можете видеть, что я в основном пересылаю обработку этих методов AppDelegate класс, который, как вы хотели настроить вещи.

AppDelegate.h:

@interface AppDelegate : NSObject <NSApplicationDelegate> {
    IBOutlet NSWindow                    *window;
    IBOutlet NSTextField                *foobazTextField;

    NSString                            *foobaz;
}
- (NSString *)foobaz;
- (void)setFoobaz:(NSString *)aFoobaz;
@end

Эта настройка позволяет вам получить и установить пользовательские foobaz свойство через AppleScript. Установка значения приведет к значению, указанному в foobaz: текстовое поле, чтобы изменить значение, которое вы установите, как показано на рисунке ниже:

Пример проекта: http://www.markdouma.com/developer/SimpleScriptingAppDelegate.zip

Единственное, что я вижу несерьезно, - это проблема в вашем sdef. Код для этой строки должен быть "capp". Это стандартно, и это будет то же самое в любом файле sdef. Это определяется Apple, так что вам это нужно.

<class name="application" code="smaa" inhereits="application"
      description="Application object.">

После того, как вы это сделаете, вы получите доступ к этому методу, как этот...

tell application "StautsMenuApp" to foobaz
Другие вопросы по тегам