无法在具有AppleScript支持的Core-data应用程序中使用Make New命令的引用

时间:2013-09-15 18:20:57

标签: cocoa core-data applescript

我能够为我的应用程序支持AppleScript的Make New命令,但是为核心数据管理对象返回的“指定对象”(NSUniqueIDSpecifier)是无用的。以下AppleScript返回错误消息:

  

错误“SpellAnalysis收到错误:密钥表单无效。”编号-10002,来自级别ID“x-coredata:/// Levels / tC5A49E01-1CE1-4ED6-8F6B-BC0AE90E279A2”

tell application "SpellAnalysis"
  set thisLevel to make new «class Slev» with properties {«class Saln»:3}
  get properties of thisLevel
end tell

因此,AppleScript中无法对新创建的Levels对象执行操作。我已经梳理了Web以获得解决方案,我发现最接近的是Bill Cheeseman的示例应用程序,“WareroomDemo”,它专门处理Cocoa Scriptability for Core Data应用程序(Sketch示例不使用Core Data)。不幸的是,这是一个过时的例子,仅在64位之前的XCode上运行而我实际上无法运行它 - 我只能查看代码。他的应用程序的Make Command可能对我所知道的所有内容都有相同的限制。

返回的'objectSpecifier'无法将创建的对象引用为防止损坏Core Data的组织方案的安全措施,或者可能因为返回的对象是未兑现的“故障”。我认为后一种可能性是不可能的,因为我可以通过获取托管对象的属性值来强制故障,但是我得到了与AppleScript相同的错误消息。

以下是创建我的类的方法:

- (id)newScriptingObjectOfClass:(Class)class forValueForKey:(NSString *)key withContentsValue:(id)contentsValue properties:(NSDictionary *)properties { // Creates a new Lesson object in response to the AppleScript 'make' command.

 // Documentation for 'newScriptingObject…' states that to create a new class object when using Core Data, you intercede using the following method (or you  can subclass the NSCreateCommand's 'performDefaultImplementation' method and put your NSManagedObject init code there):

if (class == [Levels class]) {
    //NSLog(@"class: %@",class);

   NSEntityDescription *levelsEntity = [NSEntityDescription
                                           entityForName:@"Levels"
                                    inManagedObjectContext:levelsDBase];

    NSManagedObject *levelObject = [[NSManagedObject alloc] initWithEntity:levelsEntity insertIntoManagedObjectContext:levelsDBase];
    SLOG(@"lessonObject: %@", lessonObject);

    NSString *levelNumberString = [[properties objectForKey:@"levelNumber"] stringValue];
    SLOG(@"levelNumberString: %@", levelNumberString);

    [levelObject setValue:levelNumberString forKey:@"levelNumber"];

    return levelObject; // When using Core Data, it seems that you return the newly created object directly

}

return [super newScriptingObjectOfClass:(Class)class forValueForKey:(NSString *)key withContentsValue:(id)contentsValue properties:(NSDictionary *)properties]; 
}

这是我的对象说明符方法:

- (NSScriptObjectSpecifier *)objectSpecifier {
// This NSScriptObjectSpecifiers informal protocol returns a unique ID specifier specifying the absolute string of the URI representation of this managed object.   // AppleScript return value: 'level id <id>'.

// The primary container is the application.
NSScriptObjectSpecifier *containerRef = nil; // I understand that if the application is the container, this is value you use for the container reference

NSString *uniqueID = [[[self objectID] URIRepresentation] absoluteString];

return [[[NSUniqueIDSpecifier alloc] initWithContainerClassDescription:[NSScriptClassDescription classDescriptionForClass:[NSApp class]] containerSpecifier:containerRef key:@"levelsArray" uniqueID:uniqueID] autorelease];
}

1 个答案:

答案 0 :(得分:1)

问题在于说明符方法。 Sketch示例实际上使用了我需要的技术。我多次忽略它,因为我没有看到它如何应用于Core Data托管对象。您可以使用'indexOfObjectIdenticalTo:'方法返回managedObject索引,而不是返回对象uniqueID,如下所示:

- (NSScriptObjectSpecifier *)objectSpecifier {

NSArray *levelsArray = [[NSApp delegate] levelsArray]; // Access your exposed to-many relationship--a mutable array
unsigned index = [levelsArray indexOfObjectIdenticalTo:self]; // Determin the current objects index

if (index != (unsigned)NSNotFound) {
// The primary container is the document containing this object's managed object context.
NSScriptObjectSpecifier *containerRef = nil; // the appliation
   return [[[NSIndexSpecifier allocWithZone:[self zone]] initWithContainerClassDescription:[NSScriptClassDescription classDescriptionForClass:[NSApp class]] containerSpecifier:containerRef key:@"levelsArray" index:index] autorelease];
} else {
    return nil;
}

}

请注意,此方法位于Core Data managedObject的子类中 - 在本例中为“Levels”类。 'indexOfObjectIndenticalToSelf:'方法中的'self'指的是当前正在处理的managedObject('Levels')。另外,请务必在'sdef'文件中提供说明符(访问者)类型,如下所示:

 <element type="level">
    <cocoa key="levelsArray"/>
    <accessor style="index"/>
 </element>