这就是我所拥有的:
1)在'Info.plist
中包含适当的“权限”条目2)在类扩展“element”标记中包含元素“element”标记:
`<class-extension extends="application" description="The application and top-level scripting object.">
<!-- various property tags go here -->
<element type="object item" access="r">
<cocoa key="theseObjects"/>
</element>
</class-extension>`
3)包括元素类标记:
<class name="object item" code="Objs" description="Application 'too many' object collection" plural="object items" inherits="item"> // I don't believe 'inherits' name is critical for AS to work
<cocoa class="ObjectItem"/>
</class>
4)包括将“NSApplication”脚本支持转发给其委托的委托方法:
- (BOOL)application:(NSApplication *)sender delegateHandlesKey:(NSString *)key {
if ([key isEqualToString:@"theseObjects"]) {
return YES;
}
return NO;
}
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访问器方法:
- (NSArray *)theseObjects;
{
ObjectItem *thisObject = [[ObjectItem new] autorelease];
NSArray *thisArray = [NSArray arrayWithObject:thisObject];
return thisArray;
}
}
7)创建一个AppleScript,它从我的元素getter方法返回对象:
tell application "SpellAnalysis"
get theseObjects
end tell
8)结果: 错误“未定义变量对象。”数字-2753来自“对象”
9)拔掉我的头发
答案 0 :(得分:3)
关于最初的一对多帖子,作者做了一个很好的工作,概述了脚本几乎的工作步骤。幸运的是,只需要进行一些小的修改就可以解决问题:
1)样本AppleScript
tell application "SpellAnalysis" to get theseObjects
不可能奏效。 AS不能引用Objective-C变量名称( theseObjects )。 由于 sdef 定义了“对象项”的类和元素类型,因此必须在脚本中使用:
tell application "SpellAnalysis" to get object items -- FIX #1
2)ObjectItem类中的对象说明符应返回当前对象的实际名称属性值,而不是字符串@“objectName”。所以它应该是:
- (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;
}
3)支持上述内容的完整且正确的 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="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>
4)支持上述的ObjectItem.h接口:
@interface ObjectItem : NSObject
@property (nonatomic, strong) NSString *name;
- (instancetype)initWithName:(NSString *)name;
@end
5)支持上述的ObjectItem.m文件:
#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
6)最后,App委托类中的代码支持上述内容:
#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"
答案 1 :(得分:0)
我认为我应该发布关于Cocoa Scriptability支持核心数据应用程序的一些附加信息,因为那里的信息很少。我花了至少一个月的时间试图了解如何与这种机制达成协议。
虽然我能够使用索引说明符为我的核心数据应用程序提供AppleScript支持,但我发现使用'uniqueID'说明符提供了更好的选择。更好,因为核心数据到多个关系由无序集支持,而不是数组。核心数据为您提供了一种方法,您可以通过可由Cocoa Scriptability方法评估的对象ID来指定托管对象。然而,要使用uniqueID说明符实现对“太多”关系的支持,需要额外的代码元素。
1)在'sdef'中为您将支持的每个实体提供一个property元素。例如,为了支持我的“级别”实体,我在'levels'类标记中发布以下内容:
<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>
请注意,类型被指定为“text”而不是“说明符”。 AppleEvent机制和Cocoa AppleScript支持之间的“uniqueID”交换将是一个字符串值。另请注意,'cocoa key'值为'uniqueID'。 AppleScript脚本支持支持使用此密钥('sdef'中典型的此类密钥)来识别应用程序中符合KVC模式的方法名称。
2)在包含目标对象的类中发布'valueInWithUniqueID'方法。在此方法中,您提供了一种方法来提取与传递给方法的“uniqueID”相对应的托管对象。这是我的'levelsArray'KVO方法在我的容器类中发布的'Levels'。
- (id)valueInLevelsArrayWithUniqueID:(NSString *)uniqueID;
{
NSManagedObject *managedObject= [[[NSApp delegate] myManagedObjectContext] objectWithID:[[[NSApp delegate] lessonsManager] managedObjectIDForURIRepresentation:[NSURL URLWithString:uniqueID]]];
return managedObject;
}
这是包含'单元'类的'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>
我的'Units'类也唤起了value方法。请注意基本的KVC名称模式:
- (id)valueInUnitsArrayWithUniqueID:(NSString *)uniqueID;
{
NSManagedObject *managedObject= [[[NSApp delegate] lessonsDBase] objectWithID:[[[NSApp delegate] lessonsManager] managedObjectIDForURIRepresentation:[NSURL URLWithString:uniqueID]]];
return managedObject;
}
有了这些,如果我的AppleScript需要从'uniqueID'指定'level'对象,它将被回答。当您拥有实体类的层次结构并且编写AppleScript时,这似乎会发挥作用,1)唤起一个返回对其结果的引用的命令,并且2)使用另一个命令对此返回的结果进行操作:
count (make new section at unit 1 of level 1)
奇怪的是,以下内容没有引出价值方法:
count (unit 1 of level 1)
请注意,它缺少条件1 - 缺少主要命令(例如“make”)。在这种情况下,隐含的AppleScript“get”命令被引发,但Cocoa脚本可视性似乎通过另一种方式确定实体层次结构的值。
3)为从您支持的命令返回的所有对象提供“uniqueID”对象说明符,并为支持其隐含的“get”命令的每个实体子类显式命名为“objectSpecifier”。例如,我在其'performDefaultImplementation'中发布的'clone'命令提供了以下方法:
NSUniqueIDSpecifier *uniqueIDSpecifier = [[[NSUniqueIDSpecifier allocWithZone:[self zone]] initWithContainerClassDescription:[NSScriptClassDescription classDescriptionForClass:[NSApp class]] containerSpecifier:sourceContainerSpecifier key:sourceKey uniqueID:uniqueID] autorelease];
根据您是使用命令操作单个对象还是一系列对象,可以直接返回“uniqueIDSpecifier”或将其添加到上次添加后返回的连续此类说明符的数组中。要支持隐含的“get”命令,请在每个托管对象实体子类中发布“uniqueID”对象说明符。以下说明符支持我的'Unit'类子类:
- (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;
}
请注意,第二个注释行表示我将此说明符的结果发布到全局变量中,以便包含的类的对象说明符可以将此说明符结果用作其容器说明符。应用程序委托是一个地方,所有实体子类都可以访问应用程序范围的访问器和方法,例如此对象说明符结果。
我希望上个月能帮到像我这样的人。