Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c Cocoa脚本:拦截任何对象优先消息调用 我在COCOA脚本编写自己的非Objc框架(想想在C、C++或java中编写脚本化的MAC应用程序,或者在我的例子中,Xojo)。_Objective C_Macos_Cocoa_Applescript_Cocoa Scripting - Fatal编程技术网

Objective c Cocoa脚本:拦截任何对象优先消息调用 我在COCOA脚本编写自己的非Objc框架(想想在C、C++或java中编写脚本化的MAC应用程序,或者在我的例子中,Xojo)。

Objective c Cocoa脚本:拦截任何对象优先消息调用 我在COCOA脚本编写自己的非Objc框架(想想在C、C++或java中编写脚本化的MAC应用程序,或者在我的例子中,Xojo)。,objective-c,macos,cocoa,applescript,cocoa-scripting,Objective C,Macos,Cocoa,Applescript,Cocoa Scripting,我希望能够拦截任何对象优先的方法调用,而不必将实际的方法添加到ObjC类中(我不能,因为框架不知道应用程序代码可以预先处理哪条消息——因此,一旦它们从脚本引擎传入,它就必须接收并传递任何命令消息) 例如,任何属性getter和setter都可以通过实现 -valueForUndefinedKey: -setValue:forUndefinedKey: 以及NSScriptKeyValueCoding协议的所有方法 我正在寻找一种类似的方法来截获发送到这些sdef元素中指定的方法的NSComma

我希望能够拦截任何对象优先的方法调用,而不必将实际的方法添加到ObjC类中(我不能,因为框架不知道应用程序代码可以预先处理哪条消息——因此,一旦它们从脚本引擎传入,它就必须接收并传递任何命令消息)

例如,任何属性getter和setter都可以通过实现

-valueForUndefinedKey:
-setValue:forUndefinedKey:
以及
NSScriptKeyValueCoding
协议的所有方法

我正在寻找一种类似的方法来截获发送到这些sdef元素中指定的方法的
NSCommandScript
消息:

<responds-to command="reload">
    <cocoa method="reloadList:"/>
</responds-to>
调用请求
重新加载列表:
。但是,同样的方法也被用于许多其他目的,因此我不想盲目地拦截每一个这样的调用,因为如果我将它们全部转发给一个Java函数,告诉我它是否要处理它们,这将导致相当严重的性能损失


我希望在进一步转发之前,我能告诉您,此选择器与NSScriptCommand相关。

如果它不是基于Cocoa的应用程序,那么您最好忘记使用Cocoa脚本,因为它与Cocoa体系结构的其余部分紧密耦合,使用
NSAppleEventManager
直接安装自己的AE处理程序,并在这些处理程序和最终实现模型的任何处理程序之间编写自己的视图控制器。另见:


< P> ETA:想想看,你可能想在网络上翻找一下,看看你是否能挖掘出任何一个老的C++ AEOM框架,因为在前OS X天里有一两个。可能需要一些更新,可能好也可能不好(但CS也相当糟糕),但这比从头开始容易得多,因为设计和实现一个好的、健壮的、惯用的(甚至是简化的)AEOM框架是一个巨大的PITA,即使你知道自己在做什么(几乎没有人知道).

在指定的命令处理方法中设置断点后,我看到了以下堆栈跟踪:

#0  0x00000001000197db in -[SKTRectangle rotate:]
#1  0x00007fff8ee0b7bc in __invoking___ ()
#2  0x00007fff8ee0b612 in -[NSInvocation invoke] ()
#3  0x00007fff8eeab5c6 in -[NSInvocation invokeWithTarget:] ()
#4  0x00007fff8b82cbde in -[NSScriptCommand _sendToRemainingReceivers] ()
#5  0x00007fff8b82cf39 in -[NSScriptCommand executeCommand] ()
这表明NSScriptCommand似乎没有使用任何可自定义的特殊转发机制,而是使用NSInvocation来调用该方法

这样的调用可以像这样被拦截:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    // Look for signatures with exactly one ":"
    if ([[NSStringFromSelector(aSelector) componentsSeparatedByString:@":"] count] == 2) {
        return [NSMethodSignature signatureWithObjCTypes:"@:@@"];
    } else {
        return [super methodSignatureForSelector:aSelector];
    }
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    id arg; // The first and only argument is expected to be of type NSScriptCommand*
    [anInvocation getArgument:&arg atIndex:2];
    if ([arg isKindOfClass:[NSScriptCommand class]]) {
        NSLog(@"executing the command...");
        // when finished, set the return value (which shall be an NSObject)
        id result = nil;
        [anInvocation setReturnValue:&result];
    } else {
        // oops - we cannot handle this
        [super forwardInvocation:anInvocation];
    }
}
这种形式的截取比使用
resolveInstanceMethod:
效果更好,因为它不会经常被调用,而只是为了特定的目的,例如执行NSScriptCommand

但是,问题是,如果其他代码也使用NSInvocation为其他目的调用同一类,并且这些调用使用匹配的选择器签名,则上述代码将拦截这些调用,然后不处理它们,可能导致意外行为


只要已知类仅由脚本引擎使用,并且没有其他行为(即,它们是NSObject的直接子类),就没有理由发生这种情况。因此,在我的特殊情况下,类仅作为另一个环境的代理,这可能是一个可行的解决方案。

尽管您做出了假设,但我已经完全实现了该框架。这一切都是可行的,我唯一缺少的就是以有效的方式处理对象优先命令。事实上,使用旧的API是我第一次尝试的,而这更难实现。Cocoa脚本框架已经为我解决了很多问题。
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    // Look for signatures with exactly one ":"
    if ([[NSStringFromSelector(aSelector) componentsSeparatedByString:@":"] count] == 2) {
        return [NSMethodSignature signatureWithObjCTypes:"@:@@"];
    } else {
        return [super methodSignatureForSelector:aSelector];
    }
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    id arg; // The first and only argument is expected to be of type NSScriptCommand*
    [anInvocation getArgument:&arg atIndex:2];
    if ([arg isKindOfClass:[NSScriptCommand class]]) {
        NSLog(@"executing the command...");
        // when finished, set the return value (which shall be an NSObject)
        id result = nil;
        [anInvocation setReturnValue:&result];
    } else {
        // oops - we cannot handle this
        [super forwardInvocation:anInvocation];
    }
}