尝试使用Objective-C中的Scripting Bridge在Apple Remote Desktop中自动查看计算机:
@try {
SBApplication *RD = [SBApplication applicationWithBundleIdentifier:@"com.apple.RemoteDesktop"];
// (code to check for ARD running and installed omitted here)
[RD activate]; // works just fine
RemoteDesktopComputer *computer = [[[RD classForScriptingClass:@"computer"] alloc] initWithProperties:
[NSDictionary dictionaryWithObjectsAndKeys:
ipAddress,@"InternetAddress", // looked up from header
nil
]
];
// attempt to add it to a container first:
[(SBElementArray*)[(RemoteDesktopApplication*)RD computers] addObject:computer];
// this is what raises the exception:
[computer observeZooming:Nil];
}
@catch (NSException *e) {
NSLog(@"Exception: %@", [e description]);
}
运行此命令会在日志中产生以下异常:
Exception: *** -[SBProxyByClass observeZooming:]: object has not been added to a container yet; selector not recognized [self = 0x6050004819b3]
我已经完成了与此主题相关的研究,并且已经了解到SB并不是最容易处理的因为它是如何连线的,但是任何专家或本地脚本桥的老手(没有第二方框架或obj-c以外的语言,非常感谢。
执行链接到ScriptingBridge.framework和导入Remote Desktop.h的所有先决条件 - 类型转换是为了避免在构建时出现不可避免的链接时错误...
编辑1:阅读SBObject(RemoteDesktopComputer的父级)上的文档说它是一个引用而不是一个实际的实例,你可以通过调用SBObject的get方法获取它(返回id)。所以我也试过运行它,但遗憾的是收到了相同的结果:
[[computer get] observeZooming:Nil];
以下是关于SBObject的文档:https://developer.apple.com/library/mac/documentation/cocoa/Reference/SBObject_Class/SBObject/SBObject.html#//apple_ref/occ/instm/SBObject/get
还在努力......
答案 0 :(得分:2)
(FWIW,我已经有了以下如何写,所以我将它留在这里以供将来参考。)
Scripting Bridge充其量只是一个80/20/80“解决方案”(即80%的工作时间,20%的失败时间,80%的时间你不知道为什么) 。试图与SB争论的时候,在AppleScript中打破完美运行的东西是没有意义的 - 苹果工程师负责按照这种方式设计它并且干脆拒绝接受他们打破规范[1]并搞砸了。因此,AppleScript语言的所有其他缺陷仍然是唯一支持的解决方案,可以保证正确地说出Apple事件[2]。
幸运的是,从OS X 10.6开始,还有另一种选择:使用ObjC来处理所有常规编程,并且只能通过 AppleScript-ObjC 桥接器调用AppleScript。
根据您的ObjC代码的POV,基于AppleScript的ASOC“类”或多或少与常规ObjC类无法区分。它需要一些摆弄设置,并且在过桥时你会付出一点代价,但考虑到替代品的残缺,不可靠的性质,对于任何非平凡的事情,它是最不可靠的支持选项。
假设您已经有一个现有的基于ObjC的项目,这里是如何添加一个基于ASOC的类:
目标> APPNAME>构建阶段>将二进制文件链接到库,添加AppleScriptObjC.framework
。
在支持文件中> main.m
,添加导入和加载行,如下所示:
#import <Cocoa/Cocoa.h>
#import <AppleScriptObjC/AppleScriptObjC.h>
int main(int argc, const char * argv[]) {
[[NSBundle mainBundle] loadAppleScriptObjectiveCScripts];
return NSApplicationMain(argc, argv);
}
要定义一个可从ObjC调用的名为MyStuff
的基于ASOC的类,请创建一个声明其公共方法的MyStuff.h
接口文件:
// MyStuff.h
#import <Cocoa/Cocoa.h>
@interface MyStuff : NSObject
// (note: C primitives are only automatically bridged when calling from AS into ObjC;
// AS-based methods with boolean/integer/real parameters or results use NSNumber*)
-(NSNumber *)square:(NSNumber *)aNumber;
@end
以及包含其实现的MyStuff.applescript
文件:
-- MyStuff.applescript
script MyStuff
property parent : class "NSObject"
on square_(aNumber)
return aNumber ^ 2
end square_
end script
因为MyStuff
类没有ObjC实现,所以链接器无法在构建时将ObjC代码链接到它。相反,使用NSClassFromString()
在运行时查找类对象:
#import "MyClass.h"
...
MyStuff *stuff = [[NSClassFromString(@"MyStuff") alloc] init];
否则它与正常使用的本机ObjC类几乎无法区分:
NSNumber *result = [stuff square: @3];
NSLog(@"Result: %@", result);
HTH
-
[1] Apple管理层在首次发布后不久就分拆了原来的AppleScript团队,导致其设计师退出响应,因此很多关于这些东西应该如何工作的知识丢失了。特别是,在设计脚本支持时,应用程序开发人员从未制定完整,正式的规范,因此他们所能做的就是使用个人判断和最佳猜测,然后针对AppleScript进行测试以检查其是否符合预期。因此,AppleScript自己的Apple事件桥是事实上的规范,在过去的二十年里,每个可编写脚本的应用程序都已被实现,因此其他AE桥接器能够正常工作的唯一方法就是模仿它们AS自己的桥梁,直到每一个查询和怪癖 - 不幸的是,当前的AS团队重复无法理解[2]。
[2]支持自动化的Apple支持的Apple活动同样糟糕,并且偶然也会被破坏。
答案 1 :(得分:0)
脚本桥是一个有缺陷的,混乱的混乱,因此当应用程序命令无法工作时,您不知道问题是SB是有缺陷的还是应用程序本身是错误的,或者只是要求您以不同的方式对其进行短语。
因此,第一步是在AS中编写测试脚本以查看它在那里工作。如果确实如此,它的SB就是垃圾;如果没有,请尝试摆弄您的AS代码(例如,尝试以不同的方式填写at
参数的引用,或者完全省略它),直到它为止。
您还应该询问Apple的AppleScript用户和ARD邮件列表以及ARD脚本编写者可能会出现的其他任何地方,因为大多数应用程序的脚本文档都非常不合适,所以很多关于如何做事的知识都是口。 (你真正想与之交谈的是John C Welch,又名@bynkii
,因为他是ARD脚本的大师。)