不能 JSExport 具有多个参数的 Objective-C 方法吗?

Posted

技术标签:

【中文标题】不能 JSExport 具有多个参数的 Objective-C 方法吗?【英文标题】:Can't JSExport an Objective-C Method With More Than One Parameter? 【发布时间】:2014-04-24 18:07:09 【问题描述】:

考虑一下:

@protocol FooExport <JSExport>
- (void)method1:(NSString *)param1;
- (void)method2:(NSString *)param1 param2:(NSString *)param2;
@end

@interface Foo : NSObject <FooExport>
@end

@implementation Foo
- (void)method1:(NSString *)param1 
    NSLog(@"method1");

- (void)method2:(NSString *)param1 param2:(NSString *)param2 
    NSLog(@"method2");

@end


    sContext = [[JSContext alloc] init];
    if (sContext)
    
        sContext[@"foo"] = [[Foo alloc] init];
        [sContext evaluateScript:@"foo.method1(\"foo\");"]; // method1 is called
        [sContext evaluateScript:@"foo.method2(\"foo\", \"bar\");"]; // method2 is NOT called
    

method1 被调用得很好,但是 method2 从来没有被调用过。

如果我将方法 2 更改如下:

@protocol FooExport <JSExport>
- (void)method1:(NSString *)param1;
- (void)method2:(NSString *)param1;
@end

method2 现在通过 [sContext evaluateScript:@"foo.method2(\"foo\", \"bar\");"]; (而且我必须通过 JSContext.currentArguments 挖掘出第二个参数)。

同样,如果我将方法 2 更改如下:

@protocol FooExport - (void)method1:(NSString *)param1; - (无效)方法2; @结束

method2 再次通过 [sContext evaluateScript:@"foo.method2(\"foo\", \"bar\");"]; 调用(而且我必须通过 JSContext.currentArguments 挖掘出这两个参数)。

这是设计使然吗? JSContext.currentArguments 的缺点是我必须处理 JSValues 而不是已经转换的 Objective-C 类型。

【问题讨论】:

【参考方案1】:

快速浏览 JSContext.h 会发现这个宝石:

// When a selector that takes one or more arguments is converted to a javascript
// property name, by default a property name will be generated by performing the
// following conversion:
//  - All colons are removed from the selector
//  - Any lowercase letter that had followed a colon will be capitalized.
// Under the default conversion a selector "doFoo:withBar:" will be exported as
// "doFooWithBar". The default conversion may be overriden using the JSExportAs
// macro, for example to export a method "doFoo:withBar:" as "doFoo":
//
//    @protocol MyClassJavaScriptMethods <JSExport>
//    JSExportAs(doFoo,
//    - (void)doFoo:(id)foo withBar:(id)bar
//    );
//    @end
//
// Note that the JSExport macro may only be applied to a selector that takes one
// or more argument.
#define JSExportAs(PropertyName, Selector) \
    @optional Selector __JS_EXPORT_AS__##PropertyName:(id)argument; @required Selector

【讨论】:

如果有任何用处,JSExportAs 在 Swift 上不可用,但我发现这是一个不错的选择:gist.github.com/zeitiger/1387f7d996f64b493608 如何将 JSExport 与完成处理程序一起使用? @Ian 您可以在 JSExport 原型和类中的函数定义前添加 @objc(shortJSname:),以便在 JS 世界中为方法提供不同的名称。每个参数添加一个冒号(命名或不命名)

以上是关于不能 JSExport 具有多个参数的 Objective-C 方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

swift 笔记:iOS与JavaScript的交互(二):JavaScriptCore:17。 JSExport相关演示

swift 笔记:iOS与JavaScript的交互(二):JavaScriptCore:10。继承JSExport协议

swift 笔记:iOS与JavaScript的交互(二):JavaScriptCore:9。暴露JSExport的协议定义

具有联接表和来自 GET 参数的多个值的高级查询

python类的继承

重载与重写