如何在 UIWebView 中从 Javascript 调用 Objective-C 方法?

发布于 2024-08-31 01:18:39 字数 1331 浏览 5 评论 0 原文

我正在使用 Phonegap 开发一个本机 iPhone 应用程序,因此一切都是用 HTML 和 JS 完成的。我正在使用 Flurry SDK 进行分析,并希望使用该

[FlurryAPI logEvent:@"EVENT_NAME"];

方法来跟踪事件。有没有办法在 JavaScript 中做到这一点?因此,在跟踪链接时,我会想象使用类似

<a onClick="flurryTrackEvent("Click_Rainbows")" href="#Rainbows">Rainbows</a>
<a onClick="flurryTrackEvent("Click_Unicorns")" href="#Unicorns">Unicorns</a>

“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 菜鸟。我已阅读 Apple 文档,但其中描述的示例都是新声明的方法,我想这可能更容易实现,因为 Obj-C 方法已经定义了。

预先感谢您的任何意见。

I'm developing a native iPhone app using Phonegap, so everything is done in HTML and JS. I am using the Flurry SDK for analytics and want to use the

[FlurryAPI logEvent:@"EVENT_NAME"];

method to track events. Is there a way to do this in Javascript? So when tracking a link I would imagine using something like

<a onClick="flurryTrackEvent("Click_Rainbows")" href="#Rainbows">Rainbows</a>
<a onClick="flurryTrackEvent("Click_Unicorns")" href="#Unicorns">Unicorns</a>

"FlurryAPI.h" has the following:

@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

I'm only interested in the logEvent method(s). If it's not clear by now, I'm comfortable with JS but a recovering Obj-C noob. I've read the Apple docs but the examples described there are all for newly declared methods and I imagine this could be simpler to implement because the Obj-C method(s) are already defined.

Thank you in advance for any input.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦明 2024-09-07 01:18:39

一种方法是在具有 shouldStartLoadEvent 的 UIWebView 上设置委托。在该事件中,您检查 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 中提供的类似动态函数调用。然而,这实施起来要复杂得多,并且可能存在安全风险。我建议实现如上面代码所示的路由逻辑。

One way to do this is to setup a delegate on the UIWebView which has the shouldStartLoadEvent. Inside that event, you check what URL the UIWebView is trying to navigate to. Now to communicate from JavaScript to Objective-C, you need to specify your own custom anchors which will trigger different actions. For example, to log something, you might decide to use the anchor "#FAPI_LogEvent_Click_Rainbows".

In JavaScript, you could have methods defined like such:

function flurryTrackEvent(text) {
  window.location.href = 'FAPI_LogEvent' + text;
}
function flurrySetUserID(userID) {
  window.location.href = 'FAPI_SetUserID' + userID;
}

Next, in Objective-C, you would implement the shouldStartLoadEvent and "capture" these href navigations, and tell the browser not to load them. You will need to split the string up yourself and call the appropriate function. Here's some code:

- (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
  }
}

The fact that the events are already defined in Objective-C doesn't really help much since you need to implement your own routing behavior to call the appropriate Objective-C method. The only way you could take advantage of the fact that the methods are already defined in Objective-C and avoid hard coding the routing logic, would be using @selectors or similar dynamic function calling which is available in Objective-C. However, this is much more complicated to implement and probably presents a security risk. I would recommend implementing the routing logic like is shown in the code above.

痴者 2024-09-07 01:18:39

PhoneGap 具有添加本机插件的功能,要为 iOS 添加 Flurry 日志事件插件,我会执行以下操作:

添加 PGFlurry PhoneGap 插件类:

PGFlurry.h

#import <PhoneGap/PGPlugin.h>

@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”的键/值对添加到“plugins”字典。

现在您应该可以像这样使用它:

<!DOCTYPE html>
<html>
  <head>
    <script src="phonegap.js" type="text/javascript"></script>
    <script src="flurry.js" type="text/javascript"></script>
    <script type="text/javascript">
      document.addEventListener("deviceready", function() {
        window.plugins.flurry.logEvent("Testing");
      }, false);
    </script>
  </head>
  <body>
  </body>
</html>

PhoneGap has functionality for adding native plugins, to add a Flurry log event plugin for iOS I would do something like this:

Add a PGFlurry PhoneGap plugin class:

PGFlurry.h

#import <PhoneGap/PGPlugin.h>

@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

Add a JavaScript plugin helper to the www folder:

Flurry.js

PhoneGap.addConstructor(function() {
  if(!window.plugins) {
    window.plugins = {};
  }

  window.plugins.flurry = {
    logEvent: function(name) {
      return PhoneGap.exec("PGFlurry.logEvent", name);
    }
  }
});

Add the plugin to PhoneGap.plist by adding a key/value pair with both the key and value being "PGFlurry" to the "plugins" dictionary.

Now you should be able to use it like this:

<!DOCTYPE html>
<html>
  <head>
    <script src="phonegap.js" type="text/javascript"></script>
    <script src="flurry.js" type="text/javascript"></script>
    <script type="text/javascript">
      document.addEventListener("deviceready", function() {
        window.plugins.flurry.logEvent("Testing");
      }, false);
    </script>
  </head>
  <body>
  </body>
</html>
神经大条 2024-09-07 01:18:39

找到我编写的 Phonegap Flurry 插件

您可以在https://github.com/designerkamal/Phonegap- Flurry-插件

You can find the Phonegap Flurry Plugin written by me at

https://github.com/designerkamal/Phonegap-Flurry-Plugin

鱼窥荷 2024-09-07 01:18:39

不要使用他们的 Objective-C 库,使用他们的 js 库,你就不必担心 Objective-C 了。 :)

Don't use their objective-c library, use their js library and you won't have to worry about objective-c. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文