尝试通过Objective-C中的脚本桥自动在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并不是最容易处理的,因为它是如何在幕后进行布线的,但是本机Scripting Bridge的任何专家或资深人士(没有第三方框架)或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

仍在尝试...

最佳答案

(FWIW,我已经写了以下“如何做”,因此,将其留在此处以备将来参考。)



如何使用AppleScript-ObjC代替Scripting Bridge

Scripting Bridge充其量是80/20/80的“解决方案”(即80%的时间有效,20%的时间失败以及80%的时间不知道为什么)。当SB中断了在AppleScript中可以很好工作的东西时,试图与SB争论是没有意义的-负责的Apple工程师以这种方式设计了它,只是拒绝接受破坏了规格[1]并搞砸了。结果,尽管存在其他所有不足,但AppleScript语言仍然是唯一可以保证正确说出Apple事件的受支持解决方案[2]。

幸运的是,自OS X 10.6起,还有另一个可用的选项:将ObjC用于所有常规编程内容,并且仅通过AppleScript-ObjC桥对IPC内容调用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调用的基于ASOC的名为MyStuff的类,请创建一个声明其公共方法的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);



高温超导

-

[1] Apple管理层在最初的AppleScript团队发布后不久就对其进行了分拆,导致其设计人员退出以进行响应,因此丢失了很多关于这些东西应该如何工作的知识。特别是,从来没有产生一个完整的正式规范供应用程序开发人员设计脚本支持时遵循,因此,他们所能做的就是使用个人判断和最佳猜测,然后对AppleScript进行测试,以确保其按预期工作。因此,AppleScript自己的Apple事件桥是事实上的规范,在过去的20年中,每个可编写脚本的应用都针对该规范进行了实现,因此,其他AE桥能够正常工作的唯一方法是,它们模仿AS自己的桥直到最后询问和怪癖-不幸的是,当前的AS团队屡次未能理解[2]。

[2]所支持的用于Apple的Automation for Automation的JavaScript事件也同样令人沮丧和崩溃。

关于objective-c - Objective-C脚本桥和Apple远程桌面,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25984559/

10-12 21:28