JavascriptCore:在JSExport中将JavaScript函数作为参数传递

5

JavascriptCore是iOS7支持的一个新框架。我们可以使用JSExport协议将objc类的一部分暴露给JavaScript。

在javascript中,我尝试传递函数作为参数。就像这样:

function getJsonCallback(json) {
        movie = JSON.parse(json)
        renderTemplate()
}
viewController.getJsonWithURLCallback("", getJsonCallback)

在我的 Objective-C 控制器中,我定义了一个协议:
@protocol FetchJsonForJS <JSExport>
 - (void)getJsonWithURL:(NSString *)URL
               callback:(void (^)(NSString *json))callback;
 - (void)getJsonWithURL:(NSString *)URL
         callbackScript:(NSString *)script;
@end

在JavaScript中,viewController.getJsonWithURLCallbackScript可以正常工作,但是viewController.getJsonWithURLCallback无法正常工作。

我是否在JSExport中使用了错误的块?谢谢。

1个回答

7
问题在于您已将回调函数定义为一个带有NSString参数的Objective-C块,但JavaScript不知道如何处理它,并且当您尝试评估viewController.getJsonWithURLCallback("", getJsonCallback)时会产生异常- 它认为第二个参数的类型是“未定义”。
相反,您需要将回调函数定义为JavaScript函数。
您可以在Objective-C中简单地使用JSValue来完成此操作。
对于其他读者,这里有一个完整的工作示例(带有异常处理):
TestHarnessViewController.h:
#import <UIKit/UIKit.h>
#import <JavaScriptCore/JavaScriptCore.h>

@protocol TestHarnessViewControllerExports <JSExport>
- (void)getJsonWithURL:(NSString *)URL callback:(JSValue *)callback;
@end

@interface TestHarnessViewController : UIViewController <TestHarnessViewControllerExports>
@end

TestHarnessViewController.m: (如果使用复制/粘贴,请删除evaluateScript内的换行符—这些是为了清晰起见添加的)


注:该文本为程序代码,不需要进行翻译。
#import "TestHarnessViewController.h"

@implementation TestHarnessViewController {
    JSContext *javascriptContext;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    javascriptContext  = [[JSContext alloc] init];
    javascriptContext[@"consoleLog"] = ^(NSString *message) {
        NSLog(@"Javascript log: %@",message);
    };
    javascriptContext[@"viewController"] = self;

    javascriptContext.exception = nil;
    [javascriptContext evaluateScript:@"
        function getJsonCallback(json) {
            consoleLog(\"getJsonCallback(\"+json+\") invoked.\");
            /* 
            movie = JSON.parse(json); 
            renderTemplate(); 
            */
        } 

        viewController.getJsonWithURLCallback(\"\", getJsonCallback);
    "];
    JSValue *e = javascriptContext.exception;
    if (e != nil && ![e isNull])
        NSLog(@"Javascript exception occurred %@", [e toString]);
}

- (void)getJsonWithURL:(NSString *)URL callback:(JSValue *)callback {
    NSString *json = @""; // Put JSON extract from URL here
    [callback callWithArguments:@[json]];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

在JavaScript中,使用do getJsonWithURLCallback("", getJsonCallback)调用函数 - (void)getJsonWithURL:(NSString *)URL callback:(JSValue *)callback时遇到了问题。我无法通过JSContext调用带有两个参数的函数,请帮忙解决。 - jnix
@jnix - 抱歉,我不理解你的评论。也许你应该发布一个新问题。 - Mike
@Mike,我是说我无法调用具有两个参数的本地objcC函数。更多细节请参见-http://stackoverflow.com/questions/22801909/calling-native-ios-method-with-two-parametres-from-uiwebview-using-jscontext问题 - jnix
3
@jnix - 你上面的评论没有解释你遇到了什么问题(尤其是因为样例答案已经适用于两个参数),但我看了你的其他问题,我发现你已经解决了它 - 通过JSExport公开的ObjC方法在涉及多个参数时会有不同的名称,objCMethod:withArgTwo:andArgThree: 在JavaScript中变成了 objCMethodWithArgTwoAndArgThree() - Mike
是的,这是真的。我在尝试了一些组合后才知道的:D 谢谢你的回复。 - jnix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接