Skip to content

Commit 3a4670a

Browse files
committed
support ios14 and promise
1 parent b2c016a commit 3a4670a

File tree

8 files changed

+283
-104
lines changed

8 files changed

+283
-104
lines changed

STMScriptMessageHandler.xcodeproj/project.pbxproj

+2
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@
327327
buildSettings = {
328328
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
329329
CODE_SIGN_STYLE = Automatic;
330+
DEVELOPMENT_TEAM = RQW526M45R;
330331
INFOPLIST_FILE = STMScriptMessageHandler/Info.plist;
331332
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
332333
LD_RUNPATH_SEARCH_PATHS = (
@@ -344,6 +345,7 @@
344345
buildSettings = {
345346
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
346347
CODE_SIGN_STYLE = Automatic;
348+
DEVELOPMENT_TEAM = RQW526M45R;
347349
INFOPLIST_FILE = STMScriptMessageHandler/Info.plist;
348350
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
349351
LD_RUNPATH_SEARCH_PATHS = (
+110-74
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,111 @@
11
<!doctype html>
2-
<html><head>
3-
<meta http-equiv="Content-Type" content="text/html; charset=utf8">
4-
<title>Demo</title>
5-
<style type='text/css'>
6-
html { font-family:Helvetica; color:#222; }
7-
h1 { color:steelblue; font-size:24px; margin-top:24px; }
8-
button { margin:0 3px 10px; font-size:12px; }
9-
.logLine { border-bottom:1px solid #ccc; padding:4px 2px; font-family:courier; font-size:11px; }
10-
</style><script language="javascript">
11-
var uniqueId = 1;
12-
var testCallback;
13-
14-
var JSBridge = window.Bridge;
15-
var JSPage = window.Page;
16-
17-
function log(message, data) {
18-
var log = document.getElementById('log')
19-
var el = document.createElement('div')
20-
el.className = 'logLine'
21-
el.innerHTML = uniqueId++ + '. ' + message + ':<br/>' + JSON.stringify(data)
22-
if (log.children.length) { log.insertBefore(el, log.children[0]) }
23-
else { log.appendChild(el) }
24-
}
25-
26-
function setRightButtons() {
27-
var buttons = [{ "title": '按钮0' }, { "title": '按钮1' }];
28-
log('JS calling native method "setButtons"', buttons);
29-
JSPage.callHandler('setButtons', {'callback': 'handleTapButtonAction', 'data': buttons}, function (result) {
30-
log('JS got native `setButtons` response', result);
31-
});
32-
}
33-
34-
function nslog(data) {
35-
JSBridge.callHandler('nslog', data, function (data) {
36-
log('JS got native `nslog` response', data);
37-
});
38-
}
39-
40-
function test(data) {
41-
if (testCallback) {
42-
log('calling callback', data);
43-
testCallback(data);
44-
} else {
45-
log('callback is undefined');
46-
}
47-
}
48-
49-
JSBridge.callHandler('testNativeMethod', { foo: 'foo', bar: 'bar' }, function (data) {
50-
log('JS got native `testNativeMethod` response', data);
51-
});
52-
53-
JSBridge.registerHandler('log', function (data, callback) {
54-
var message = data;
55-
log('Native calling js method `log`', message);
56-
callback({ key: 'from js', value: data });
57-
});
58-
59-
JSBridge.registerHandler('test', function(data, callback) {
60-
log('save callback');
61-
testCallback = callback;
62-
});
63-
64-
JSPage.registerHandler('handleTapButtonAction', function(index) {
65-
var response = '点击了按钮' + index;
66-
log('Native calling js method `handleTapButtonAction`', response);
67-
});
68-
69-
</script>
70-
</head><body>
71-
<input type="button" value="Set Right Buttons" onclick="setRightButtons()" />
72-
<input type="button" value="nslog" onclick="nslog({'foo': 'foo'})" />
73-
<input type="button" value="test callback" onclick="test({'key': 'value'})" />
74-
<div id='log'></div>
75-
</body></html>
2+
<html>
3+
4+
<head>
5+
<meta http-equiv="Content-Type" content="text/html; charset=utf8">
6+
<title>Demo</title>
7+
<style type='text/css'>
8+
html {
9+
font-family: Helvetica;
10+
color: #222;
11+
}
12+
13+
h1 {
14+
color: steelblue;
15+
font-size: 24px;
16+
margin-top: 24px;
17+
}
18+
19+
button {
20+
margin: 0 3px 10px;
21+
font-size: 12px;
22+
}
23+
24+
.logLine {
25+
border-bottom: 1px solid #ccc;
26+
padding: 4px 2px;
27+
font-family: courier;
28+
font-size: 11px;
29+
}
30+
</style>
31+
<script language="javascript">
32+
var uniqueId = 1;
33+
var testCallback;
34+
35+
var JSBridge = window.Bridge;
36+
var JSPage = window.Page;
37+
38+
function log(message, data) {
39+
var log = document.getElementById('log')
40+
var el = document.createElement('div')
41+
el.className = 'logLine'
42+
el.innerHTML = uniqueId++ + '. ' + message + ':<br/>' + JSON.stringify(data)
43+
if (log.children.length) { log.insertBefore(el, log.children[0]) }
44+
else { log.appendChild(el) }
45+
}
46+
47+
function setRightButtons() {
48+
var buttons = [{ "title": '按钮0' }, { "title": '按钮1' }];
49+
log('JS calling native method "setButtons"', buttons);
50+
JSPage.callHandler('setButtons', { 'callback': 'handleTapButtonAction', 'data': buttons }, function (result) {
51+
log('JS got native `setButtons` response', result);
52+
});
53+
}
54+
55+
function nslog(data) {
56+
JSBridge.callHandler('nslog', data, function (data) {
57+
log('JS got native `nslog` response', data);
58+
});
59+
}
60+
61+
async function promise(data) {
62+
// JSBridge.callHandler('nslog', data).then(
63+
// result => log('JS got native `nslog` response', result),
64+
// error => log('JS got native `nslog` error', error)
65+
// )
66+
67+
var p = JSBridge.callHandler('nslog', data);
68+
var result = await p;
69+
log('JS got native `nslog` response', result);
70+
}
71+
72+
function test(data) {
73+
if (testCallback) {
74+
log('calling callback', data);
75+
testCallback(data);
76+
} else {
77+
log('callback is undefined');
78+
}
79+
}
80+
81+
JSBridge.callHandler('testNativeMethod', { foo: 'foo', bar: 'bar' }, function (data) {
82+
log('JS got native `testNativeMethod` response', data);
83+
});
84+
85+
JSBridge.registerHandler('log', function (data, callback) {
86+
var message = data;
87+
log('Native calling js method `log`', message);
88+
callback({ key: 'from js', value: data });
89+
});
90+
91+
JSBridge.registerHandler('test', function (data, callback) {
92+
log('save callback');
93+
testCallback = callback;
94+
});
95+
96+
JSPage.registerHandler('handleTapButtonAction', function (index) {
97+
var response = '点击了按钮' + index;
98+
log('Native calling js method `handleTapButtonAction`', response);
99+
});
100+
</script>
101+
</head>
102+
103+
<body>
104+
<input type="button" value="Set Right Buttons" onclick="setRightButtons()" />
105+
<input type="button" value="nslog" onclick="nslog({'foo': 'foo'})" />
106+
<input type="button" value="promise" onclick="promise({'bar': 'bar'})" />
107+
<input type="button" value="test callback" onclick="test({'key': 'value'})" />
108+
<div id='log'></div>
109+
</body>
110+
111+
</html>

STMScriptMessageHandler/Source/STMScriptMessageHandler.h

+20-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
11
//
22
// STMScriptMessageHandler.h
3-
// Pods-STMWebViewController_Example
43
//
5-
// Created by DouKing on 2018/7/31.
4+
// Copyright (c) 2021-2025 DouKing (https://github.com/DouKing/)
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files (the "Software"), to deal
8+
// in the Software without restriction, including without limitation the rights
9+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
// copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions:
12+
//
13+
// The above copyright notice and this permission notice shall be included in
14+
// all copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
// THE SOFTWARE.
623
//
724

825
@import UIKit;
@@ -13,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN
1330
typedef void (^STMResponseCallback)(id responseData);
1431
typedef void (^STMHandler)(id data, STMResponseCallback _Nullable responseCallback);
1532

16-
@interface STMScriptMessageHandler : NSObject<WKScriptMessageHandler>
33+
@interface STMScriptMessageHandler : NSObject<WKScriptMessageHandler, WKScriptMessageHandlerWithReply>
1734

1835
@property (nonatomic, copy, readonly) NSString *handlerName;
1936

STMScriptMessageHandler/Source/STMScriptMessageHandler.m

+44-9
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,39 @@
11
//
22
// STMScriptMessageHandler.m
3-
// Pods-STMWebViewController_Example
43
//
5-
// Created by DouKing on 2018/7/31.
4+
// Copyright (c) 2021-2025 DouKing (https://github.com/DouKing/)
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files (the "Software"), to deal
8+
// in the Software without restriction, including without limitation the rights
9+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
// copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions:
12+
//
13+
// The above copyright notice and this permission notice shall be included in
14+
// all copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
// THE SOFTWARE.
623
//
724

825
#import "STMScriptMessageHandler.h"
926
#import "STMScriptMessageHandler_JS.h"
1027

1128
#define STM_JS_FUNC(x, ...) [NSString stringWithFormat:@#x ,##__VA_ARGS__]
12-
#define WEAK_SELF __weak typeof(self) __weak_self__ = self
13-
#define STRONG_SELF __strong typeof(__weak_self__) self = __weak_self__
14-
15-
static NSString * const kSTMApp = @"App";
16-
static NSString * const kSTMNativeCallback = @"nativeCallback";
17-
static NSString * const kSTMMethodHandlerReuseKey = @"kSTMMethodHandlerReuseKey";
18-
static NSString * const kSTMMethodHandlerIMPKey = @"kSTMMethodHandlerIMPKey";
1929

2030
static NSString * const kSTMMessageParameterNameKey = @"handlerName";
2131
static NSString * const kSTMMessageParameterInfoKey = @"data";
2232
static NSString * const kSTMMessageParameterResponseKey = @"responseData";
2333
static NSString * const kSTMMessageParameterCallbackIdKey = @"callbackId";
2434
static NSString * const kSTMMessageParameterResponseIdKey = @"responseId";
35+
static NSString * const kSTMMessageParameterResolveIdKey = @"resolveId";
36+
static NSString * const kSTMMessageParameterReplyKey = @"kSTMMessageParameterReplyKey";
2537

2638
static int gSTMCallbackUniqueId = 1;
2739

@@ -117,6 +129,19 @@ - (void)_flushReceivedMessage:(NSDictionary *)message {
117129
};
118130
} else {
119131
responseCallback = ^(id responseData){
132+
if (!responseData) {
133+
responseData = [NSNull null];
134+
}
135+
void (^replyHandler)(id _Nullable reply, NSString *_Nullable errorMessage) = message[kSTMMessageParameterReplyKey];
136+
NSString *resolveId = message[kSTMMessageParameterResolveIdKey];
137+
if (replyHandler) {
138+
replyHandler(responseData, nil);
139+
} else if (resolveId) {
140+
[self _dispatchMessage:@{
141+
kSTMMessageParameterResponseIdKey: resolveId,
142+
kSTMMessageParameterResponseKey: responseData,
143+
}];
144+
}
120145
};
121146
}
122147
}
@@ -192,6 +217,16 @@ - (void)userContentController:(WKUserContentController *)userContentController d
192217
[self _flushReceivedMessage:message.body];
193218
}
194219

220+
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message replyHandler:(void (^)(id _Nullable reply, NSString *_Nullable errorMessage))replyHandler API_AVAILABLE(macos(11.0), ios(14.0)) {
221+
if (![message.name isEqualToString:self.handlerName]) { return; }
222+
223+
NSMutableDictionary *parameters = [message.body mutableCopy];
224+
parameters[kSTMMessageParameterReplyKey] = replyHandler ?: ^(id _Nullable reply, NSString *_Nullable errorMessage){
225+
NSLog(@"reply handler is nil");
226+
};
227+
[self _flushReceivedMessage:parameters];
228+
}
229+
195230
#pragma mark - setter & getter
196231

197232
- (NSMutableDictionary *)methodHandlers {

STMScriptMessageHandler/Source/STMScriptMessageHandler_JS.h

+19-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
11
//
22
// STMScriptMessageHandler_JS.h
3-
// STMScriptMessageHandler
43
//
5-
// Created by DouKing on 2021/2/26.
4+
// Copyright (c) 2021-2025 DouKing (https://github.com/DouKing/)
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files (the "Software"), to deal
8+
// in the Software without restriction, including without limitation the rights
9+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
// copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions:
12+
//
13+
// The above copyright notice and this permission notice shall be included in
14+
// all copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
// THE SOFTWARE.
623
//
724

825
#import <Foundation/Foundation.h>

0 commit comments

Comments
 (0)