Objective-C的脚本桥接和苹果远程桌面 [英] Objective-C Scripting Bridge and Apple Remote Desktop

查看:110
本文介绍了Objective-C的脚本桥接和苹果远程桌面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试自动通过脚本大桥在Objective-C查看苹果远程桌面的计算机与此:

Trying to automatically view a computer in Apple Remote Desktop via Scripting Bridge in Objective-C with this:


    @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]);
    }

运行这就产生日志中的以下异常:

Running this yields the following exception in the log:

    Exception: *** -[SBProxyByClass observeZooming:]: object has not been added to a container yet; selector not recognized [self = 0x6050004819b3]

因为有可用的关于这个问题,并已得知SB是不是最容易处理,因为它是如何在引擎盖下与有线,但任何专家或本地脚本桥接的退伍军人(不,我已经做了尽可能多的研究第三方框架或比OBJ-C等语言,请)是多少AP preciated。

I've done as much research as there is available on this subject and have learned that SB isn't the easiest to deal with because of how it's wired under the hood, but any experts or veterans of native Scripting Bridge (no third party frameworks or languages other than obj-c, please) is much appreciated.

所有prerequisites像链接到ScriptingBridge.framework和导入远程Desktop.h执行 - 的类型转化,以避免出现哪些是不可避免的链接时错误时,建设...

All prerequisites like linking to the ScriptingBridge.framework and importing Remote Desktop.h are performed - the typecasts are to avoid what appear to be unavoidable link-time errors when building...

编辑1:阅读SBObject的文档(RemoteDesktopComputer的母公司)说,这是一个参考,而不是一个实际的例子,你可以通过调用SBObject的get方法(返回ID)获取。所以我尝试运行此也无奈接受了相同的结果:

Edit 1: Reading the documentation on SBObject (parent of RemoteDesktopComputer) says that it's a reference rather than an actual instance, which you can fetch by calling SBObject's get method (returns id). So I tried running this as well but unfortunately received the same results:

    [[computer get] observeZooming:Nil];

下面是关于SBObject的文档:<一href=\"https://developer.apple.com/library/mac/documentation/cocoa/Reference/SBObject_Class/SBObject/SBObject.html#//apple_ref/occ/instm/SBObject/get\" rel=\"nofollow\">https://developer.apple.com/library/mac/documentation/cocoa/Reference/SBObject_Class/SBObject/SBObject.html#//apple_ref/occ/instm/SBObject/get

Here's the documentation on SBObject: https://developer.apple.com/library/mac/documentation/cocoa/Reference/SBObject_Class/SBObject/SBObject.html#//apple_ref/occ/instm/SBObject/get

仍在尝试...

推荐答案

(FWIW,我已经有了下面的如何写了,所以我在这里留下以备日后参考。)

(FWIW, I already had the following How To written up, so I'm leaving it here for future reference.)

脚本桥,充其量一个80/20/80解决方案(即它的工作80%的时间,它的失败,20%的时间,而80%的时间你不知道为什么) 。有小点,试图用SB争论时,它打破的东西,在AppleScript的工作得很好 - 负责苹果的工程师设计是故意那样,简单地拒绝接受他们打破了规范[1]和搞砸了。其结果是,在的AppleScript语言,它的所有其他不足,保持的的这是保证正确地讲Apple事件支持的解决方案[2]

Scripting Bridge is, at best, an 80/20/80 "solution" (i.e. 80% of the time it works, 20% of the time it fails, and 80% of the time you've no idea why). There's little point trying to argue with SB when it breaks on stuff that works perfectly well in AppleScript - the Apple engineers responsible designed it that way on purpose and simply refuse to accept they broke spec [1] and screwed up. As a result, the AppleScript language, for all its other deficiencies, remains the only supported solution that is guaranteed to speak Apple events correctly [2].

幸运的是,因为OS X 10.6也已经提供另一种选择:使用ObjC你所有的通用编程的东西,只能通过在 AppleScript的ObjC 桥的IPC东西调入的AppleScript。

Fortunately, since OS X 10.6 there has been another option available: use ObjC for all your general programming stuff, and only call into AppleScript via the AppleScript-ObjC bridge for the IPC stuff.

从你ObjC code的POV,您的基于AppleScript的ASOC类从正规ObjC类或多或少的区别。这需要一点摆弄成立,并过桥时,你将支付通行费的一点,但考虑到替代品的残废的,不可靠的性质,它的任何东西不平凡支持的选项是最可怕的。

From the POV of your ObjC code, your AppleScript-based ASOC 'classes' are more or less indistinguishable from regular ObjC classes. It requires a bit of fiddling to set up, and you'll pay a bit of a toll when crossing the bridge, but given the crippled, unreliable nature of the alternatives, it's the least horrid of the supported options for anything non-trivial.

假设你已经有了一个现有的基于ObjC项目,这里是如何在基于ASOC类添加到它:

Assuming you've already got an existing ObjC-based project, here's how to add an ASOC-based class to it:


  1. 在目标> APPNAME>构建阶段>链接二进制库,添加 AppleScriptObjC.framework

在支持文件> main.m文件,加上进口和负载线,如图:

In Supporting Files > main.m, add the import and load lines as shown:

#import <Cocoa/Cocoa.h>
#import <AppleScriptObjC/AppleScriptObjC.h>

int main(int argc, const char * argv[]) {
   [[NSBundle mainBundle] loadAppleScriptObjectiveCScripts];
   return NSApplicationMain(argc, argv);
}


  • 要定义一个名为基于ASOC级的MyStuff 这是从ObjC调用,创建一个 MyStuff.h 接口文件:

  • To define an ASOC-based class named MyStuff that's callable from ObjC, create a MyStuff.h interface file that declares its public methods:

    // 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 code在编译时链接到它。相反,使用 NSClassFromString()来查找类对象在运行时:

  • Because the MyStuff class doesn't have an ObjC implementation, the linker can't link your ObjC code to it at build-time. Instead, use NSClassFromString() to look up the class object at run-time:

    #import "MyClass.h"
    
    ...
    
    MyStuff *stuff = [[NSClassFromString(@"MyStuff") alloc] init];
    

    否则,它是pretty在正常使用本地ObjC类区分多少:

    Otherwise it's pretty much indistinguishable from a native ObjC class in normal use:

    NSNumber *result = [stuff square: @3];
    NSLog(@"Result: %@", result);
    


  • 心连心

    -

    [1]苹果管理打破了原有的AppleScript团队首次发布后不久,导致其设计者为响应退出,所以很多$ P $的知识pcisely怎么这东西应该工作丢了。尤其是一个完整的,正式的规范从未被生产为应用开发者设计他们的脚本支持时要遵循的,所以他们现在能做的就是用个人的判断和最佳猜测,然后进行测试针对的AppleScript检查它担任希望。因此,AppleScript的自己的苹果事件的桥是的事实上的标准的,每一个脚本化的应用程序已对在过去20年来实现的,这样其他AE桥梁都不能正常工作的唯一方法是,如果他们模仿AS自身的桥到每一个最后的查询和夸克 - 一个教训,遗憾的是,目前的AS团队的重复的不明白[2]

    [1] Apple management broke up the original AppleScript team shortly after its initial release, causing its designers to quit in response, so a lot of knowledge of precisely how this stuff should work was lost. In particular, a full, formal specification was never produced for application developers to follow when designing their scripting support, so all they could do was use personal judgement and best guesses, then test against AppleScript to check it worked as hoped. Thus, AppleScript's own Apple event bridge is the de facto specification that every single scriptable app has been implemented against in the last twenty years, so the only way that other AE bridges can ever work correctly is if they mimic AS's own bridge down to every last query and quirk - a lesson, unfortunately, that the current AS team have repeatedly failed to understand [2].

    [2]的JavaScript支持自动化的苹果事件同样蹩脚和捣毁,顺便说一句。

    [2] JavaScript for Automation's Apple event supported is equally crappy and busted, incidentally.

    这篇关于Objective-C的脚本桥接和苹果远程桌面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆