Merge branch 'main' of https://git.shuto.cn/public/cordova-shuto-api
This commit is contained in:
@@ -40,6 +40,26 @@ cordova.plugins.ShutoApi.getUserInfo(
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### ionicReady()
|
||||||
|
标识前端应用已就绪。调用此方法后,原生代码中的事件管理器会触发 `ionicReady` 事件。
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
cordova.plugins.ShutoApi.ionicReady();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
建议在应用初始化完成后调用:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
document.addEventListener('deviceready', function() {
|
||||||
|
// 应用初始化逻辑...
|
||||||
|
|
||||||
|
// 通知原生代码前端已就绪
|
||||||
|
cordova.plugins.ShutoApi.ionicReady();
|
||||||
|
}, false);
|
||||||
|
```
|
||||||
|
|
||||||
### 事件
|
### 事件
|
||||||
|
|
||||||
#### navigate
|
#### navigate
|
||||||
@@ -169,8 +189,86 @@ cordova.plugins.ShutoApi.removeEventListener('navigate', handleNavigate);
|
|||||||
|
|
||||||
## 原生代码使用
|
## 原生代码使用
|
||||||
|
|
||||||
|
### 独立事件管理器(ShutoEventManager)
|
||||||
|
|
||||||
|
插件提供了独立的事件管理器 `ShutoEventManager`,用于在原生代码中进行事件的监听和触发。这与Cordova插件分离,可以在任何原生代码中使用。
|
||||||
|
|
||||||
|
#### 事件列表
|
||||||
|
|
||||||
|
- `ionicReady`: 当前端调用 `ionicReady()` 方法时触发
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### iOS
|
### iOS
|
||||||
|
|
||||||
|
#### 1. 导入头文件
|
||||||
|
|
||||||
|
```objective-c
|
||||||
|
#import "ShutoEventManager.h"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### 2. 注册事件监听
|
||||||
|
|
||||||
|
```objective-c
|
||||||
|
// 让类遵循 ShutoEventListener 协议
|
||||||
|
@interface YourViewController () <ShutoEventListener>
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation YourViewController
|
||||||
|
|
||||||
|
- (void)viewDidLoad {
|
||||||
|
[super viewDidLoad];
|
||||||
|
|
||||||
|
// 注册 ionicReady 事件监听
|
||||||
|
[[ShutoEventManager sharedInstance] addListenerForEvent:@"ionicReady" listener:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实现协议方法
|
||||||
|
- (void)onEvent:(NSString *)eventName data:(NSDictionary *)data {
|
||||||
|
if ([eventName isEqualToString:@"ionicReady"]) {
|
||||||
|
NSLog(@"前端已就绪,可以执行后续操作");
|
||||||
|
// 在这里处理前端就绪后的逻辑
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
// 移除所有事件监听
|
||||||
|
[[ShutoEventManager sharedInstance] removeListener:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### 3. 移除事件监听
|
||||||
|
|
||||||
|
```objective-c
|
||||||
|
// 移除特定事件的监听
|
||||||
|
[[ShutoEventManager sharedInstance] removeListenerForEvent:@"ionicReady" listener:self];
|
||||||
|
|
||||||
|
// 移除所有事件的监听
|
||||||
|
[[ShutoEventManager sharedInstance] removeListener:self];
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### 4. 触发自定义事件
|
||||||
|
|
||||||
|
```objective-c
|
||||||
|
// 触发事件(可带数据)
|
||||||
|
NSDictionary *eventData = @{
|
||||||
|
@"key": @"value",
|
||||||
|
@"timestamp": @([NSDate timeIntervalSinceReferenceDate])
|
||||||
|
};
|
||||||
|
[[ShutoEventManager sharedInstance] fireEvent:@"customEvent" data:eventData];
|
||||||
|
|
||||||
|
// 触发事件(不带数据)
|
||||||
|
[[ShutoEventManager sharedInstance] fireEvent:@"customEvent" data:nil];
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### 5. 通过插件实例触发事件(Cordova相关)
|
||||||
|
|
||||||
在iOS原生代码中,可以通过以下方式触发事件:
|
在iOS原生代码中,可以通过以下方式触发事件:
|
||||||
|
|
||||||
```objective-c
|
```objective-c
|
||||||
@@ -233,6 +331,74 @@ NSDictionary* fetchData = @{
|
|||||||
|
|
||||||
### Android
|
### Android
|
||||||
|
|
||||||
|
#### 1. 导入类
|
||||||
|
|
||||||
|
```java
|
||||||
|
import cn.shuto.feishuapi.ShutoEventManager;
|
||||||
|
import cn.shuto.feishuapi.ShutoEventListener;
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### 2. 注册事件监听
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class YourActivity extends AppCompatActivity implements ShutoEventListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
|
// 注册 ionicReady 事件监听
|
||||||
|
ShutoEventManager.getInstance().addListener("ionicReady", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实现接口方法
|
||||||
|
@Override
|
||||||
|
public void onEvent(String eventName, Map<String, Object> data) {
|
||||||
|
if ("ionicReady".equals(eventName)) {
|
||||||
|
Log.d("YourActivity", "前端已就绪,可以执行后续操作");
|
||||||
|
// 在这里处理前端就绪后的逻辑
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
// 移除所有事件监听
|
||||||
|
ShutoEventManager.getInstance().removeListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### 3. 移除事件监听
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 移除特定事件的监听
|
||||||
|
ShutoEventManager.getInstance().removeListener("ionicReady", this);
|
||||||
|
|
||||||
|
// 移除所有事件的监听
|
||||||
|
ShutoEventManager.getInstance().removeListener(this);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### 4. 触发自定义事件
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 触发事件(可带数据)
|
||||||
|
Map<String, Object> eventData = new HashMap<>();
|
||||||
|
eventData.put("key", "value");
|
||||||
|
eventData.put("timestamp", System.currentTimeMillis());
|
||||||
|
ShutoEventManager.getInstance().fireEvent("customEvent", eventData);
|
||||||
|
|
||||||
|
// 触发事件(不带数据)
|
||||||
|
ShutoEventManager.getInstance().fireEvent("customEvent");
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### 5. 通过插件实例触发事件(Cordova相关)
|
||||||
|
|
||||||
在Android原生代码中,可以通过以下方式触发事件:
|
在Android原生代码中,可以通过以下方式触发事件:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
</feature>
|
</feature>
|
||||||
</config-file>
|
</config-file>
|
||||||
<source-file src="src/android/ShutoApi.java" target-dir="src/cn/shuto/feishuapi" />
|
<source-file src="src/android/ShutoApi.java" target-dir="src/cn/shuto/feishuapi" />
|
||||||
|
<source-file src="src/android/ShutoEventManager.java" target-dir="src/cn/shuto/feishuapi" />
|
||||||
|
<source-file src="src/android/ShutoEventListener.java" target-dir="src/cn/shuto/feishuapi" />
|
||||||
</platform>
|
</platform>
|
||||||
<platform name="ios">
|
<platform name="ios">
|
||||||
<config-file parent="/*" target="config.xml">
|
<config-file parent="/*" target="config.xml">
|
||||||
@@ -21,5 +23,7 @@
|
|||||||
</feature>
|
</feature>
|
||||||
</config-file>
|
</config-file>
|
||||||
<source-file src="src/ios/ShutoApi.m" />
|
<source-file src="src/ios/ShutoApi.m" />
|
||||||
|
<source-file src="src/ios/ShutoEventManager.h" />
|
||||||
|
<source-file src="src/ios/ShutoEventManager.m" />
|
||||||
</platform>
|
</platform>
|
||||||
</plugin>
|
</plugin>
|
||||||
@@ -14,6 +14,9 @@ import org.json.JSONArray;
|
|||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements a Cordova plugin for Shuto API.
|
* This class implements a Cordova plugin for Shuto API.
|
||||||
*/
|
*/
|
||||||
@@ -27,6 +30,9 @@ public class ShutoApi extends CordovaPlugin {
|
|||||||
// 保存带回调的事件回调映射
|
// 保存带回调的事件回调映射
|
||||||
private Map<String, EventCallback> eventCallbacks = new HashMap<>();
|
private Map<String, EventCallback> eventCallbacks = new HashMap<>();
|
||||||
|
|
||||||
|
// 标识前端是否就绪
|
||||||
|
private boolean isIonicReady = false;
|
||||||
|
|
||||||
// 事件回调接口
|
// 事件回调接口
|
||||||
public interface EventCallback {
|
public interface EventCallback {
|
||||||
void onResult(JSONObject result);
|
void onResult(JSONObject result);
|
||||||
@@ -48,6 +54,9 @@ public class ShutoApi extends CordovaPlugin {
|
|||||||
this.eventCallback(args);
|
this.eventCallback(args);
|
||||||
callbackContext.success();
|
callbackContext.success();
|
||||||
return true;
|
return true;
|
||||||
|
} else if (action.equals("ionicReady")) {
|
||||||
|
this.ionicReady(callbackContext);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -178,4 +187,19 @@ public class ShutoApi extends CordovaPlugin {
|
|||||||
LOG.e(TAG, "error", e);
|
LOG.e(TAG, "error", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理前端就绪状态
|
||||||
|
private void ionicReady(CallbackContext callbackContext) {
|
||||||
|
isIonicReady = true;
|
||||||
|
LOG.d(TAG, "Ionic is ready");
|
||||||
|
|
||||||
|
ShutoEventManager.getInstance().fireEvent("ionicReady");
|
||||||
|
|
||||||
|
callbackContext.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提供给原生代码查询就绪状态的接口
|
||||||
|
public boolean isIonicReady() {
|
||||||
|
return isIonicReady;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package cn.shuto.feishuapi;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件监听器接口
|
||||||
|
*/
|
||||||
|
public interface ShutoEventListener {
|
||||||
|
void onEvent(String eventName, Map<String, Object> data);
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package cn.shuto.feishuapi;
|
||||||
|
|
||||||
|
import org.apache.cordova.LOG;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 独立的事件管理类,用于在原生代码中进行事件的监听注册与触发
|
||||||
|
*/
|
||||||
|
public class ShutoEventManager {
|
||||||
|
private static final String TAG = "ShutoEventManager";
|
||||||
|
|
||||||
|
private static ShutoEventManager instance;
|
||||||
|
|
||||||
|
private Map<String, Set<ShutoEventListener>> eventListeners;
|
||||||
|
|
||||||
|
private ShutoEventManager() {
|
||||||
|
eventListeners = new ConcurrentHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized ShutoEventManager getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new ShutoEventManager();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addListener(String eventName, ShutoEventListener listener) {
|
||||||
|
if (eventName == null || listener == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
eventListeners.computeIfAbsent(eventName, k -> new CopyOnWriteArraySet<>()).add(listener);
|
||||||
|
LOG.d(TAG, "Added listener for event: " + eventName + ", total listeners: " + eventListeners.get(eventName).size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeListener(String eventName, ShutoEventListener listener) {
|
||||||
|
if (eventName == null || listener == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<ShutoEventListener> listeners = eventListeners.get(eventName);
|
||||||
|
if (listeners != null) {
|
||||||
|
listeners.remove(listener);
|
||||||
|
LOG.d(TAG, "Removed listener for event: " + eventName + ", remaining listeners: " + listeners.size());
|
||||||
|
|
||||||
|
if (listeners.isEmpty()) {
|
||||||
|
eventListeners.remove(eventName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeListener(ShutoEventListener listener) {
|
||||||
|
if (listener == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Set<ShutoEventListener> listeners : eventListeners.values()) {
|
||||||
|
listeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
eventListeners.entrySet().removeIf(entry -> entry.getValue().isEmpty());
|
||||||
|
LOG.d(TAG, "Removed listener from all events");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fireEvent(String eventName, Map<String, Object> data) {
|
||||||
|
if (eventName == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.d(TAG, "Firing event: " + eventName + ", data: " + data);
|
||||||
|
|
||||||
|
Set<ShutoEventListener> listeners = eventListeners.get(eventName);
|
||||||
|
if (listeners != null && !listeners.isEmpty()) {
|
||||||
|
for (ShutoEventListener listener : listeners) {
|
||||||
|
listener.onEvent(eventName, data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG.d(TAG, "No listeners for event: " + eventName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fireEvent(String eventName) {
|
||||||
|
fireEvent(eventName, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
#import <Cordova/CDV.h>
|
#import <Cordova/CDV.h>
|
||||||
#import <WebKit/WebKit.h>
|
#import <WebKit/WebKit.h>
|
||||||
#import "SGGC_Log.h"
|
#import "SGGC_Log.h"
|
||||||
|
#import "ShutoEventManager.h"
|
||||||
|
|
||||||
@protocol ShutoApiProtocol <NSObject>
|
@protocol ShutoApiProtocol <NSObject>
|
||||||
- (void)fireEvent:(NSString*)type parameters:(NSDictionary*)parameters;
|
- (void)fireEvent:(NSString*)type parameters:(NSDictionary*)parameters;
|
||||||
@@ -16,6 +17,8 @@
|
|||||||
NSDictionary* _userInfo;
|
NSDictionary* _userInfo;
|
||||||
// 保存带回调的事件回调ID映射
|
// 保存带回调的事件回调ID映射
|
||||||
NSMutableDictionary* _eventCallbacks;
|
NSMutableDictionary* _eventCallbacks;
|
||||||
|
// 标识前端是否就绪
|
||||||
|
BOOL _isIonicReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)close:(CDVInvokedUrlCommand*)command;
|
- (void)close:(CDVInvokedUrlCommand*)command;
|
||||||
@@ -26,6 +29,8 @@
|
|||||||
- (void)fireEvent:(NSString*)type parameters:(NSDictionary*)parameters;
|
- (void)fireEvent:(NSString*)type parameters:(NSDictionary*)parameters;
|
||||||
- (void)fireEventWithCallback:(NSString*)eventName parameters:(NSDictionary*)parameters callback:(void (^)(NSDictionary* result, NSError* error))callback;
|
- (void)fireEventWithCallback:(NSString*)eventName parameters:(NSDictionary*)parameters callback:(void (^)(NSDictionary* result, NSError* error))callback;
|
||||||
- (void)eventCallback:(CDVInvokedUrlCommand*)command;
|
- (void)eventCallback:(CDVInvokedUrlCommand*)command;
|
||||||
|
- (void)ionicReady:(CDVInvokedUrlCommand*)command;
|
||||||
|
- (BOOL)isIonicReady;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation ShutoApi
|
@implementation ShutoApi
|
||||||
@@ -209,4 +214,20 @@
|
|||||||
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)ionicReady:(CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
_isIonicReady = YES;
|
||||||
|
[SGGC_Log log:@"SGGC_CDVFile" message:@"ShutoApi: Ionic is ready"];
|
||||||
|
|
||||||
|
[[ShutoEventManager sharedInstance] fireEvent:@"ionicReady" data:nil];
|
||||||
|
|
||||||
|
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
|
||||||
|
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isIonicReady
|
||||||
|
{
|
||||||
|
return _isIonicReady;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// ShutoEventManager.h
|
||||||
|
// ShutoApi
|
||||||
|
//
|
||||||
|
// Created by Shuto Team.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@protocol ShutoEventListener <NSObject>
|
||||||
|
- (void)onEvent:(NSString *)eventName data:(NSDictionary *)data;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface ShutoEventManager : NSObject
|
||||||
|
|
||||||
|
+ (instancetype)sharedInstance;
|
||||||
|
|
||||||
|
- (void)addListenerForEvent:(NSString *)eventName listener:(id<ShutoEventListener>)listener;
|
||||||
|
- (void)removeListenerForEvent:(NSString *)eventName listener:(id<ShutoEventListener>)listener;
|
||||||
|
- (void)removeListener:(id<ShutoEventListener>)listener;
|
||||||
|
- (void)fireEvent:(NSString *)eventName data:(NSDictionary *)data;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
//
|
||||||
|
// ShutoEventManager.m
|
||||||
|
// ShutoApi
|
||||||
|
//
|
||||||
|
// Created by Shuto Team.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ShutoEventManager.h"
|
||||||
|
#import "SGGC_Log.h"
|
||||||
|
|
||||||
|
@interface ShutoEventManager ()
|
||||||
|
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSMutableSet<id<ShutoEventListener>> *> *eventListeners;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation ShutoEventManager
|
||||||
|
|
||||||
|
+ (instancetype)sharedInstance {
|
||||||
|
static ShutoEventManager *instance = nil;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
instance = [[ShutoEventManager alloc] init];
|
||||||
|
});
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)init {
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
_eventListeners = [[NSMutableDictionary alloc] init];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addListenerForEvent:(NSString *)eventName listener:(id<ShutoEventListener>)listener {
|
||||||
|
if (!eventName || !listener) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@synchronized(self.eventListeners) {
|
||||||
|
if (!self.eventListeners[eventName]) {
|
||||||
|
self.eventListeners[eventName] = [[NSMutableSet alloc] init];
|
||||||
|
}
|
||||||
|
[self.eventListeners[eventName] addObject:listener];
|
||||||
|
[SGGC_Log log:@"ShutoEventManager" message:[NSString stringWithFormat:@"Added listener for event: %@, total listeners: %lu", eventName, (unsigned long)self.eventListeners[eventName].count]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeListenerForEvent:(NSString *)eventName listener:(id<ShutoEventListener>)listener {
|
||||||
|
if (!eventName || !listener) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@synchronized(self.eventListeners) {
|
||||||
|
if (self.eventListeners[eventName]) {
|
||||||
|
[self.eventListeners[eventName] removeObject:listener];
|
||||||
|
[SGGC_Log log:@"ShutoEventManager" message:[NSString stringWithFormat:@"Removed listener for event: %@, remaining listeners: %lu", eventName, (unsigned long)self.eventListeners[eventName].count]];
|
||||||
|
|
||||||
|
if (self.eventListeners[eventName].count == 0) {
|
||||||
|
[self.eventListeners removeObjectForKey:eventName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeListener:(id<ShutoEventListener>)listener {
|
||||||
|
if (!listener) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@synchronized(self.eventListeners) {
|
||||||
|
NSMutableArray *emptyEvents = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
|
for (NSString *eventName in self.eventListeners.allKeys) {
|
||||||
|
NSMutableSet *listeners = self.eventListeners[eventName];
|
||||||
|
if ([listeners containsObject:listener]) {
|
||||||
|
[listeners removeObject:listener];
|
||||||
|
[SGGC_Log log:@"ShutoEventManager" message:[NSString stringWithFormat:@"Removed listener from event: %@, remaining listeners: %lu", eventName, (unsigned long)listeners.count]];
|
||||||
|
|
||||||
|
if (listeners.count == 0) {
|
||||||
|
[emptyEvents addObject:eventName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.eventListeners removeObjectsForKeys:emptyEvents];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)fireEvent:(NSString *)eventName data:(NSDictionary *)data {
|
||||||
|
if (!eventName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[SGGC_Log log:@"ShutoEventManager" message:[NSString stringWithFormat:@"Firing event: %@, data: %@", eventName, data]];
|
||||||
|
|
||||||
|
NSArray *listeners = nil;
|
||||||
|
@synchronized(self.eventListeners) {
|
||||||
|
if (self.eventListeners[eventName]) {
|
||||||
|
listeners = [self.eventListeners[eventName] allObjects];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listeners && listeners.count > 0) {
|
||||||
|
for (id<ShutoEventListener> listener in listeners) {
|
||||||
|
if ([listener respondsToSelector:@selector(onEvent:data:)]) {
|
||||||
|
[listener onEvent:eventName data:data];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
[SGGC_Log log:@"ShutoEventManager" message:[NSString stringWithFormat:@"No listeners for event: %@", eventName]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -12,6 +12,11 @@ var ShutoApi = {
|
|||||||
// 执行带回调的事件
|
// 执行带回调的事件
|
||||||
executeEvent: function (eventName, params, success, error) {
|
executeEvent: function (eventName, params, success, error) {
|
||||||
exec(success, error, 'ShutoApi', 'executeEvent', [eventName, params]);
|
exec(success, error, 'ShutoApi', 'executeEvent', [eventName, params]);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 标识前端已就绪
|
||||||
|
ionicReady: function (success, error) {
|
||||||
|
exec(success, error, 'ShutoApi', 'ionicReady', []);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user