如何支持application(NSApp)类的AppleScript元素(一对多关系)?

如何支持application(NSApp)类的AppleScript元素(一对多关系)?,applescript,element,one-to-many,sdef,Applescript,Element,One To Many,Sdef,以下是我所拥有的: 1) 在“Info.plist”中包含适当的“权限”条目 “可编写脚本”:是 “脚本定义文件名”:myApp.sdef 2) 将元素“element”标记包含在类扩展“element”标记中: } 5) 创建“ObjectItem”类并将对象说明符放在那里: - (NSScriptObjectSpecifier *)objectSpecifier { NSScriptObjectSpecifier *containerRef = nil; NSScriptObject

以下是我所拥有的:

1) 在“Info.plist”中包含适当的“权限”条目

  • “可编写脚本”:是
  • “脚本定义文件名”:myApp.sdef
2) 将元素“element”标记包含在类扩展“element”标记中:

}

5) 创建“ObjectItem”类并将对象说明符放在那里:

 - (NSScriptObjectSpecifier *)objectSpecifier { 
NSScriptObjectSpecifier *containerRef = nil;
NSScriptObjectSpecifier *specifier = [[NSNameSpecifier alloc] initWithContainerClassDescription:[NSScriptClassDescription classDescriptionForClass:[NSApp class]] containerSpecifier:containerRef key:@"theseObjects" name:@"objectName"];
return [specifier autorelease];
6) 在应用程序的委托中发布KVO访问器方法:

- (BOOL)application:(NSApplication *)sender delegateHandlesKey:(NSString *)key {    
if ([key isEqualToString:@"theseObjects"]) {
    return YES;
}
return NO;
 - (NSArray *)theseObjects;
   {
ObjectItem *thisObject = [[ObjectItem new] autorelease];
NSArray *thisArray = [NSArray arrayWithObject:thisObject];
return thisArray;
    }
}
7) 创建从my element getter方法返回对象的AppleScript:

    tell application "SpellAnalysis"
    get theseObjects
    end tell
8) 结果是: 错误“未定义变量对象”。编号“对象”中的-2753


9) 把我的头发拔出来

我想我应该发布一些关于核心数据应用程序Cocoa脚本能力支持的补充信息,因为信息太少了。我花了至少一个月的时间试图理解如何接受这种机制

虽然我能够使用索引说明符为我的核心数据应用程序提供AppleScript支持,但我发现使用“uniqueID”说明符提供了更好的匹配。更好,因为多个关系的核心数据由无序集而不是数组支持。核心数据为您提供了一种通过对象ID指定托管对象的方法,该对象ID可以通过可编写脚本的方法进行计算。然而,要使用uniqueID说明符实现对“过多”关系的支持,需要额外的代码元素

1) 在“sdef”中为您将支持的每个实体提供属性元素。例如,为了支持我的“级别”实体,我在“级别”类标记中发布了以下内容:

<property name="id" code="ID  " type="text" access="r" description="The level's unique id. This may be a temporary id for newly-    created level objects, until they are saved.">
    <cocoa key="uniqueID"/>
</property>
下面是我对包含的“unit”类的“sdef”属性声明:

<property name="id" code="ID  " type="text" access="r" description="The unit's unique id.  This may be a temporary id for newly-created unit objects, until they are saved.">
    <cocoa key="uniqueID"/>
</property>
有了这些,如果我的AppleScript需要从它的“uniqueID”中指定一个“level”对象,它将得到响应。当您有一个实体类的层次结构,并且您编写了一个AppleScript,该AppleScript 1)调用一个命令,该命令返回对其结果的引用,2)使用另一个命令对该返回的结果进行操作时,这似乎起到了作用:

count (make new section at unit 1 of level 1)
奇怪的是,以下情况并没有引发value方法:

count (unit 1 of level 1)
请注意,它缺少条件1——缺少主命令(例如“make”)。在这种情况下,将调用隐含的AppleScript“get”命令,但是,Cocoa脚本能力似乎通过另一种方式确定实体层次结构的值

3) 为您支持的命令返回的所有对象提供“uniqueID”对象说明符,并为支持其隐含的“get”命令的每个实体子类提供显式命名的“objectSpecifier”。例如,在其“PerformDefaultmentation”中发布的我的“clone”命令提供了以下方法:

 NSUniqueIDSpecifier *uniqueIDSpecifier = [[[NSUniqueIDSpecifier allocWithZone:[self zone]]  initWithContainerClassDescription:[NSScriptClassDescription classDescriptionForClass:[NSApp class]] containerSpecifier:sourceContainerSpecifier key:sourceKey uniqueID:uniqueID] autorelease];
根据使用命令操作单个对象还是一系列对象,可以直接返回“uniqueIDSpecifier”,或将其添加到上次添加后返回的连续此类说明符数组中。为了支持隐含的“get”命令,可以在每个托管对象实体子类中发布一个“uniqueID”对象说明符。以下说明符支持我的“单位”类子类:

- (NSScriptObjectSpecifier *)objectSpecifier {
    NSScriptObjectSpecifier *containerRef = [[NSApp delegate]levelsSpecifier];
    NSString *uniqueID = [[[self objectID] URIRepresentation] absoluteString]; // This is            the key method for determining the object's 'uniqueID'
if (uniqueID) {
    NSScriptObjectSpecifier *uniqueIDSpecifier = [[[NSUniqueIDSpecifier allocWithZone:   [self zone]]   initWithContainerClassDescription:[containerRef keyClassDescription]  containerSpecifier:containerRef key:@"unitsArray" uniqueID:uniqueID] autorelease];
   [[NSApp delegate] setUnitsSpecifier:uniqueIDSpecifier]; // Post specifier so Units  class specifier can access it
    return uniqueIDSpecifier;
   } else {
      return nil;
   }
注意,第二条注释行表示我将此说明符的结果发布到一个全局变量中,以便所包含类的对象说明符可以使用此说明符结果作为其容器说明符。应用程序委托是所有实体子类都可以访问应用程序范围的访问器和方法(如此对象说明符结果)的地方


上个月,我希望这能帮助像我这样的人。

我想我应该发布一些关于核心数据应用程序Cocoa脚本能力支持的补充信息,因为信息太少了。我花了至少一个月的时间试图理解如何接受这种机制

虽然我能够使用索引说明符为我的核心数据应用程序提供AppleScript支持,但我发现使用“uniqueID”说明符提供了更好的匹配。更好,因为多个关系的核心数据由无序集而不是数组支持。核心数据为您提供了一种通过对象ID指定托管对象的方法,该对象ID可以通过可编写脚本的方法进行计算。然而,要使用uniqueID说明符实现对“过多”关系的支持,需要额外的代码元素

1) 在“sdef”中为您将支持的每个实体提供属性元素。例如,为了支持我的“级别”实体,我在“级别”类标记中发布了以下内容:

<property name="id" code="ID  " type="text" access="r" description="The level's unique id. This may be a temporary id for newly-    created level objects, until they are saved.">
    <cocoa key="uniqueID"/>
</property>
下面是我对包含的“unit”类的“sdef”属性声明:

<property name="id" code="ID  " type="text" access="r" description="The unit's unique id.  This may be a temporary id for newly-created unit objects, until they are saved.">
    <cocoa key="uniqueID"/>
</property>
有了这些,如果我的AppleScript需要从它的“uniqueID”中指定一个“level”对象,它将得到响应。当您有一个实体类的层次结构,并且您编写了一个AppleScript,该AppleScript 1)调用一个命令,该命令返回对其结果的引用,2)使用另一个命令对该返回的结果进行操作时,这似乎起到了作用:

count (make new section at unit 1 of level 1)
奇怪的是,以下情况并没有引发value方法:

count (unit 1 of level 1)
请注意,它缺少条件1——缺少主命令(例如“make”)。在这种情况下,将调用隐含的AppleScript“get”命令,但是,Cocoa脚本能力似乎通过另一种方式确定实体层次结构的值

3) 为您支持的命令返回的所有对象提供“uniqueID”对象说明符,并为支持其隐含的“get”命令的每个实体子类提供显式命名的“objectSpecifier”。例如,在其“PerformDefaultmentation”中发布的我的“clone”命令提供了以下方法:

 NSUniqueIDSpecifier *uniqueIDSpecifier = [[[NSUniqueIDSpecifier allocWithZone:[self zone]]  initWithContainerClassDescription:[NSScriptClassDescription classDescriptionForClass:[NSApp class]] containerSpecifier:sourceContainerSpecifier key:sourceKey uniqueID:uniqueID] autorelease];
根据使用命令操作单个对象还是一系列对象,可以直接返回“uniqueIDSpecifier”,或将其添加到上次添加后返回的连续此类说明符数组中。支持隐含的“获取”命令
tell application "SpellAnalysis" to get object items -- FIX #1
- (NSScriptObjectSpecifier *)objectSpecifier 
{ 
    NSScriptObjectSpecifier *containerRef = nil;
    NSScriptObjectSpecifier *specifier = [[NSNameSpecifier alloc] 
        initWithContainerClassDescription:[NSScriptClassDescription classDescriptionForClass:[NSApp class]] 
        containerSpecifier:containerRef 
        key:@"theseObjects" 
        name:self.name]; // FIX #2

    return specifier;
}
<?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="SpellAnalysis Suite" code="sSIA" description="ToDo">
        <class name="object item" code="Objs" description="ToDo" plural="object items">
            <cocoa class="ObjectItem"/> <!-- KVC: Objective-C class ObjectItem : NSObject -->
            <property name="name" code="pnam" type="text" access="r" description="Its name.">
                <cocoa key="name"/>
            </property>
        </class>
        <class-extension name="SpellAnalysis application" extends="application" description="ToDo">
            <element type="object item" access="r">
                <cocoa key="theseObjects"/> <!-- KVC: app delegate's @property NSArray* theseObjects; -->
            </element>
        </class-extension>
    </suite>
</dictionary>
@interface ObjectItem : NSObject
    @property (nonatomic, strong) NSString *name;

    - (instancetype)initWithName:(NSString *)name;
@end
#import "ObjectItem.h"
@implementation ObjectItem

- (instancetype)initWithName:(NSString *)name
{
    if (self = [super init])
    {
        self.name = name;
    }
    return self;
}

- (NSScriptObjectSpecifier *)objectSpecifier 
{ 
    NSScriptObjectSpecifier *containerRef = nil;
    NSScriptObjectSpecifier *specifier = [[NSNameSpecifier alloc] 
        initWithContainerClassDescription:[NSScriptClassDescription classDescriptionForClass:[NSApp class]] 
        containerSpecifier:containerRef 
        key:@"theseObjects" 
        name:self.name]; // FIX #2

    return specifier;
}
@end
#import "MyAppDelegate.h"
#import "ObjectItem.h"

@interface MyAppDelegate ()
@property (nonatomic, strong) NSArray *theseObjects;
@end

@implementation MyAppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    self.theseObjects = @[
        [[ObjectItem alloc] initWithName:@"Item A"],
        [[ObjectItem alloc] initWithName:@"Item B"],
        [[ObjectItem alloc] initWithName:@"Item C"]
    ];
}

- (BOOL)application:(NSApplication *)sender delegateHandlesKey:(NSString *)key
{
    if ([key isEqualToString:@"theseObjects"])
    {
        return YES;
    }
    return NO;
}
@end
tell application "SpellAnalysis"
    get object items -- expect a list of object references for all objects in array
end tell

--> {object item "Item A" of application "SpellAnalysis", object item "Item B" of application "SpellAnalysis", object item "Item C" of application "SpellAnalysis"}
tell application "SpellAnalysis"
    get object item 2 -- expect a object reference to the second item in the array
end tell

--> object item "Item B" of application "SpellAnalysis"


tell application "SpellAnalysis"
    name of object item 2 -- Expected result: the name property of 2nd obj in array
end tell

--> "Item B"