如何从UIWebView中的Javascript调用Objective-C方法?
我正在使用Phonegap开发一个原生的iPhone应用程序,所以一切都是用HTML和JS完成的。 我正在使用Flurry SDK进行分析,并希望使用
[FlurryAPI logEvent:@"EVENT_NAME"];
跟踪事件的方法。 有没有办法在Javascript中执行此操作? 因此,在跟踪链接时,我会想象使用类似的东西
Rainbows Unicorns
“FlurryAPI.h”具有以下内容:
@interface FlurryAPI : NSObject { } + (void)startSession:(NSString *)apiKey; + (void)logEvent:(NSString *)eventName; + (void)logEvent:(NSString *)eventName withParameters:(NSDictionary *)parameters; + (void)logError:(NSString *)errorID message:(NSString *)message exception:(NSException *)exception; + (void)setUserID:(NSString *)userID; + (void)setEventLoggingEnabled:(BOOL)value; + (void)setServerURL:(NSString *)url; + (void)setSessionReportsOnCloseEnabled:(BOOL)sendSessionReportsOnClose; @end
我只对logEvent方法感兴趣。 如果现在还不清楚,我对JS很满意,但是对于一个正在恢复的Obj-C noob。 我已经阅读了Apple文档,但是所描述的示例都是针对新声明的方法,我想这可能更容易实现,因为已经定义了Obj-C方法。
提前感谢您的任何输入。
一种方法是在UIWebView上设置一个具有shouldStartLoadEvent的委托。 在该事件中,您将检查UIWebView尝试导航到的URL。 现在要从JavaScript到Objective-C进行通信,您需要指定自己的自定义锚点,这将触发不同的操作。 例如,要记录某些内容,您可能决定使用锚点“#FAPI_LogEvent_Click_Rainbows”。
在JavaScript中,您可以使用如下定义的方法:
function flurryTrackEvent(text) { window.location.href = 'FAPI_LogEvent' + text; } function flurrySetUserID(userID) { window.location.href = 'FAPI_SetUserID' + userID; }
接下来,在Objective-C中,您将实现shouldStartLoadEvent并“捕获”这些href导航,并告诉浏览器不要加载它们。 您需要自己拆分字符串并调用相应的函数。 这是一些代码:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType () { NSString *theAnchor = [[request URL] fragment]; if ([theAnchor hasPrefix:@"FAPI_LogEvent"]) { NSString *textToLog = [theAnchor substringFromIndex:[@"FAPI_LogEvent" length]]; [FlurryAPI logEvent:textToLog]; return NO; // prevent the UIWebView from navigating to this anchor } else if ([theAnchor hasPrefix:@"FAPI_SetUserID"]) { NSString *userID = [theAnchor substringFromIndex:[@"FAPI_SetUserID" length]]; [FlurryAPI setUserID:userID]; return NO; // prevent the UIWebView from navigating to this anchor } }
事件已经在Objective-C中定义的事实并没有多大帮助,因为您需要实现自己的路由行为来调用适当的Objective-C方法。 您可以利用Objective-C中已定义方法并避免硬编码路由逻辑这一事实的唯一方法是使用@selectors或Objective-C中提供的类似动态函数调用。 但是,这实现起来要复杂得多,并且可能存在安全风险。 我建议实现如上面代码中所示的路由逻辑。
PhoneGap具有添加本机插件的function,为iOS添加Flurry日志事件插件我会做这样的事情:
添加PGFlurry
PhoneGap插件类:
PGFlurry.h
#import @interface PGFlurry : PGPlugin - (void)logEvent:(NSArray*)arguments withDict:(NSDictionary*)options; @end
PGFlurry.m
#import "PGFlurry.h" #import "FlurryAPI.h" @implementation PGFlurry // if you init Flurry somewhere else you can remove this method - (PGPlugin*) initWithWebView:(UIWebView*)theWebView { self = [super init]; if (self == nil) { return nil; } // init and start Flurry [FlurryAPI startSession:@"API key"]; return self; } - (void)logEvent:(NSArray*)arguments withDict:(NSDictionary*)options { [FlurryAPI logEvent:[arguments objectAtIndex:0]]; } @end
将JavaScript插件助手添加到www
文件夹:
Flurry.js
PhoneGap.addConstructor(function() { if(!window.plugins) { window.plugins = {}; } window.plugins.flurry = { logEvent: function(name) { return PhoneGap.exec("PGFlurry.logEvent", name); } } });
将插件添加到PhoneGap.plist
,将键和值“PGFlurry”添加到“插件”字典中。
现在你应该能够像这样使用它:
你可以找到我写的Phonegap Flurry插件
不要使用他们的objective-c库,使用他们的js库,你不必担心objective-c。 🙂