66//
77
88#import " STMScriptMessageHandler.h"
9+ #import " STMScriptMessageHandler_JS.h"
910
1011#define STM_JS_FUNC (x, ...) [NSString stringWithFormat: @#x ,##__VA_ARGS__]
1112#define WEAK_SELF __weak typeof (self) __weak_self__ = self
1617static NSString * const kSTMMethodHandlerReuseKey = @" kSTMMethodHandlerReuseKey" ;
1718static NSString * const kSTMMethodHandlerIMPKey = @" kSTMMethodHandlerIMPKey" ;
1819
19- static NSString * const kSTMMessageParameterNameKey = @" name" ;
20- static NSString * const kSTMMessageParameterInfoKey = @" info" ;
20+ static NSString * const kSTMMessageParameterNameKey = @" handlerName" ;
21+ static NSString * const kSTMMessageParameterInfoKey = @" data" ;
22+ static NSString * const kSTMMessageParameterResponseKey = @" responseData" ;
2123static NSString * const kSTMMessageParameterCallbackIdKey = @" callbackId" ;
22- static NSString * const kSTMMessageParameterReuseKey = @" reuse " ;
24+ static NSString * const kSTMMessageParameterResponseIdKey = @" responseId " ;
2325
2426static int gSTMCallbackUniqueId = 1 ;
2527
@@ -46,124 +48,84 @@ - (instancetype)initWithScriptMessageHandlerName:(NSString *)handlerName forWebV
4648}
4749
4850- (void )prepareJsScript {
49- [self _addJS1 ];
50- [self _addJS2 ];
51- [self _addJS3 ];
52- WEAK_SELF;
53- [self registerMethod: kSTMNativeCallback handler: ^(NSDictionary * _Nonnull data, STMResponseCallback _Nullable responseCallback) {
54- STRONG_SELF;
55- NSDictionary *info = data[kSTMMessageParameterInfoKey ];
56- NSString *callbackId = data[kSTMMessageParameterCallbackIdKey ] ?: @" " ;
57- BOOL reuse = [data[kSTMMessageParameterReuseKey ] boolValue ];
58- STMResponseCallback jsResponse = self.jsResponseHandlers [callbackId];
59- !jsResponse ?: jsResponse (info);
60- if (!reuse) {
61- [self .jsResponseHandlers removeObjectForKey: callbackId];
62- }
63- }];
51+ NSString *js = STMScriptMessageHandler_js (self.handlerName );
52+ // [self _evaluateJavaScript:js];
53+ [self _addJSScript: js forMainFrameOnly: NO ];
6454}
6555
66- - (void )registerMethod : (NSString *)methodName handler : (STMHandler)handler {
67- [self registerMethod: methodName reuseHandler: NO handler: handler];
68- }
69-
70- - (void )registerMethod : (NSString *)methodName reuseHandler : (BOOL )reuse handler : (nonnull STMHandler)handler {
56+ - (void )registerMethod : (NSString *)methodName handler : (nonnull STMHandler)handler {
7157 if (!methodName || !handler) { return ; }
7258 if (handler) {
73- self.methodHandlers [methodName] = @{kSTMMethodHandlerReuseKey : @(reuse),
74- kSTMMethodHandlerIMPKey : handler};
59+ self.methodHandlers [methodName] = handler;
7560 }
7661}
7762
78- - (void )callMethod : (NSString *)methodName parameters : (NSDictionary *)parameters responseHandler : (STMResponseCallback)handler {
63+ - (void )removeMethod : (NSString *)methodName {
64+ if (!methodName) { return ; }
65+ [self .methodHandlers removeObjectForKey: methodName];
66+ }
67+
68+ - (void )callMethod : (NSString *)methodName parameters : (id )parameters responseHandler : (STMResponseCallback)handler {
7969 if (!methodName) { return ; }
80- NSString *callbackId = @" " ;
70+ NSMutableDictionary *message = [NSMutableDictionary dictionary ];
71+ if (parameters) {
72+ message[kSTMMessageParameterInfoKey ] = parameters;
73+ }
74+
8175 if (handler) {
82- callbackId = [NSString stringWithFormat: @" cb_%d _%.0f " , gSTMCallbackUniqueId ++, [NSDate timeIntervalSinceReferenceDate ] * 1000 ];
76+ NSString * callbackId = [NSString stringWithFormat: @" cb_%d _%.0f " , gSTMCallbackUniqueId ++, [NSDate timeIntervalSinceReferenceDate ] * 1000 ];
8377 self.jsResponseHandlers [callbackId] = handler;
78+ message[kSTMMessageParameterCallbackIdKey ] = callbackId;
8479 }
85- NSString *formatParameter = [self _formatParameters: @{@" parameters" : parameters}];
86- NSString *js = STM_JS_FUNC (%@.%@.nativeCall (' %@' ,JSON.parse (' %@' ).parameters ,' %@' ), kSTMApp , self.handlerName , methodName, formatParameter, callbackId);
87- [self _evaluateJavaScript: js];
88- [self _debug: @" native call js's method" method: methodName parameters: parameters];
89- }
90-
91- #pragma mark - Private
9280
93- - (void )_response : (NSString *)methodName callbackId : (NSString *)callbackId parameter : (nullable id )parameter deleteCallback : (BOOL )delete {
94- NSString *formatParameter = [self _formatParameters: @{@" responseData" : parameter}];
95- callbackId = callbackId ?: @" " ;
96- NSString *js = STM_JS_FUNC (
97- var callback = %@.%@.callback [' %@' ];
98- if (callback) { callback (JSON.parse (' %@' ).responseData ); if (%d) { delete %@.%@.callback .%@ }}
99- , kSTMApp , self.handlerName , callbackId, formatParameter, delete, kSTMApp , self.handlerName , callbackId
100- );
101- [self _evaluateJavaScript: js];
81+ message[kSTMMessageParameterNameKey ] = methodName;
82+ [self _dispatchMessage: message];
10283}
10384
104- - (void )_addJS1 {
105- NSString *jsScript = STM_JS_FUNC (var %@ = window.webkit .messageHandlers ;, kSTMApp );
106- [self _addJSScript: jsScript forMainFrameOnly: YES ];
107- }
108-
109- - (void )_addJS2 {
110- NSString *jsScript = STM_JS_FUNC (
111- %@.%@.registerMethod = function (methodName, methodHandler, reuse) {
112- if (!%@.%@.methods ) {
113- %@.%@.methods = {};
114- }
115- var handlerInfo = {};
116- handlerInfo[' imp' ] = methodHandler;
117- handlerInfo[' reuse' ] = reuse;
118- %@.%@.methods [methodName] = handlerInfo;
119- }
120- , kSTMApp , self.handlerName ,
121- kSTMApp , self.handlerName ,
122- kSTMApp , self.handlerName ,
123- kSTMApp , self.handlerName
124- );
125- [self _addJSScript: jsScript forMainFrameOnly: YES ];
126-
127- NSString *js = STM_JS_FUNC (
128- var callbackUniqueId = 1 ;
129- if (!%@.%@.callback ) {
130- %@.%@.callback = {};
131- };
132- %@.%@.callMethod = function (name, info, callback) {
133- var message = {};
134- message[' name' ] = name;
135- message[' info' ] = info;
136- if (callback) {
137- var callbackId = ' cb_' +(callbackUniqueId++)+' _' +new Date ().getTime ();
138- %@.%@.callback [callbackId] = callback;
139- message[' callbackId' ] = callbackId;
140- }
141- %@.%@.postMessage (message);
142- };
143- , kSTMApp , self.handlerName ,
144- kSTMApp , self.handlerName ,
145- kSTMApp , self.handlerName ,
146- kSTMApp , self.handlerName ,
147- kSTMApp , self.handlerName
148- );
149- [self _addJSScript: js forMainFrameOnly: YES ];
150- }
85+ #pragma mark - Private
15186
152- - (void )_addJS3 {
153- NSString *jsScript = STM_JS_FUNC (
154- %@.%@.nativeCall = function (methodName, info, callbackId) {
155- var handlerInfo = %@.%@.methods [methodName];
156- var reuse = handlerInfo[' reuse' ];
157- var handler = handlerInfo[' imp' ];
158- handler (info, function (data){
159- %@.%@.postMessage ({name:' %@' ,info:{name:methodName,info:data,callbackId:callbackId,reuse:reuse}});
160- });
161- }
162- , kSTMApp , self.handlerName ,
163- kSTMApp , self.handlerName ,
164- kSTMApp , self.handlerName , kSTMNativeCallback
165- );
166- [self _addJSScript: jsScript forMainFrameOnly: YES ];
87+ // 给 js 端发送消息
88+ - (void )_dispatchMessage : (NSDictionary *)message {
89+ NSString *messageJSON = [self _formatParameters: message];
90+ NSString * javascriptCommand = [NSString stringWithFormat: @" %@ ._handleMessageFromObjC('%@ ');" , self .handlerName, messageJSON];
91+ [self _evaluateJavaScript: javascriptCommand];
92+ }
93+
94+ // 处理收到的 js 端消息
95+ - (void )_flushReceivedMessage : (NSDictionary *)message {
96+ if (![message isKindOfClass: NSDictionary .class]) {
97+ return ;
98+ }
99+
100+ NSString *responseId = message[kSTMMessageParameterResponseIdKey ];
101+ if (responseId) {
102+ STMResponseCallback responseCallback = self.jsResponseHandlers [responseId];
103+ !responseCallback ?: responseCallback (message[kSTMMessageParameterResponseKey ]);
104+ [self .jsResponseHandlers removeObjectForKey: responseId];
105+ } else {
106+ STMResponseCallback responseCallback; {
107+ NSString *callbackId = message[kSTMMessageParameterCallbackIdKey ];
108+ if (callbackId) {
109+ responseCallback = ^(id responseData){
110+ if (!responseData) {
111+ responseData = [NSNull null ];
112+ }
113+ [self _dispatchMessage: @{
114+ kSTMMessageParameterResponseIdKey : callbackId,
115+ kSTMMessageParameterResponseKey : responseData,
116+ }];
117+ };
118+ } else {
119+ responseCallback = ^(id responseData){
120+ };
121+ }
122+ }
123+ STMHandler handler = self.methodHandlers [message[kSTMMessageParameterNameKey ]];
124+ if (!handler) {
125+ return ;
126+ }
127+ handler (message[kSTMMessageParameterInfoKey ], responseCallback);
128+ }
167129}
168130
169131#pragma mark -
@@ -183,6 +145,7 @@ - (void)_evaluateJavaScript:(NSString *)javaScriptString {
183145 [self .webView evaluateJavaScript: javaScriptString completionHandler: ^(id _Nullable info, NSError * _Nullable error) {
184146 __strong typeof (__weak_self__) self = __weak_self__;
185147 if (error) {
148+ NSLog (@" Error: %@ " , error);
186149 [self .webView reload ];
187150 }
188151 }];
@@ -226,24 +189,7 @@ - (void)_debug:(NSString *)name method:(NSString *)method parameters:(NSDictiona
226189
227190- (void )userContentController : (WKUserContentController *)userContentController didReceiveScriptMessage : (WKScriptMessage *)message {
228191 if (![message.name isEqualToString: self .handlerName]) { return ; }
229- NSString *method = message.body [kSTMMessageParameterNameKey ];
230- NSDictionary *parameter = message.body [kSTMMessageParameterInfoKey ];
231- NSString *callbackId = message.body [kSTMMessageParameterCallbackIdKey ];
232- NSDictionary *handlerInfo = self.methodHandlers [method];
233- STMHandler handler = handlerInfo[kSTMMethodHandlerIMPKey ];
234- BOOL reuseHandler = [handlerInfo[kSTMMethodHandlerReuseKey ] boolValue ];
235- if ([method isEqualToString: kSTMNativeCallback ]) {
236- handler (parameter, nil );
237- [self _debug: @" native receive js's response" method: parameter[kSTMMessageParameterNameKey ] parameters: parameter[kSTMMessageParameterInfoKey ]];
238- } else {
239- [self _debug: @" js call native's method" method: method parameters: parameter];
240- WEAK_SELF;
241- handler (parameter, ^(id info) {
242- STRONG_SELF;
243- [self _response: method callbackId: callbackId parameter: info deleteCallback: !reuseHandler];
244- [self _debug: @" js receive native's response" method: method parameters: info];
245- });
246- }
192+ [self _flushReceivedMessage: message.body];
247193}
248194
249195#pragma mark - setter & getter
0 commit comments