Skip to content

Commit f3d2ace

Browse files
committed
Make [WebViewJavascriptBridge bridgeForWebView:] work for all web view types, including WKWebView. Fixes marcuswestin#252, marcuswestin#249.
1 parent 539d67e commit f3d2ace

File tree

10 files changed

+78
-80
lines changed

10 files changed

+78
-80
lines changed

Example Apps/ExampleApp-OSX/AppDelegate.m

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@
99
#import "AppDelegate.h"
1010
#import <WebKit/WebKit.h>
1111
#import "WebViewJavascriptBridge.h"
12-
#import "WKWebViewJavascriptBridge.h"
1312

1413
@implementation AppDelegate {
1514
WebView* _webView;
1615
WKWebView *_WKWebView;
1716
WebViewJavascriptBridge* _bridge;
18-
WKWebViewJavascriptBridge* _WKBridge;
17+
WebViewJavascriptBridge* _WKBridge;
1918
NSView* _WKWebViewWrapper;
2019
}
2120

@@ -63,7 +62,7 @@ - (void)_configureWebview {
6362

6463
- (void)_configureWKWebview {
6564
// Create Bridge
66-
_WKBridge = [WKWebViewJavascriptBridge bridgeForWebView:_WKWebView];
65+
_WKBridge = [WebViewJavascriptBridge bridgeForWebView:_WKWebView];
6766

6867
[_WKBridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {
6968
NSLog(@"testObjcCallback called: %@", data);

Example Apps/ExampleApp-iOS/ExampleWKWebViewController.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
//
88

99
#import "ExampleWKWebViewController.h"
10-
#import "WKWebViewJavascriptBridge.h"
10+
#import "WebViewJavascriptBridge.h"
1111

1212
@interface ExampleWKWebViewController ()
1313

14-
@property WKWebViewJavascriptBridge* bridge;
14+
@property WebViewJavascriptBridge* bridge;
1515

1616
@end
1717

@@ -23,8 +23,8 @@ - (void)viewWillAppear:(BOOL)animated {
2323
WKWebView* webView = [[NSClassFromString(@"WKWebView") alloc] initWithFrame:self.view.bounds];
2424
webView.navigationDelegate = self;
2525
[self.view addSubview:webView];
26-
[WKWebViewJavascriptBridge enableLogging];
27-
_bridge = [WKWebViewJavascriptBridge bridgeForWebView:webView];
26+
[WebViewJavascriptBridge enableLogging];
27+
_bridge = [WebViewJavascriptBridge bridgeForWebView:webView];
2828
[_bridge setWebViewDelegate:self];
2929

3030
[_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {

Example Apps/ExampleApp.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ <h1>WebViewJavascriptBridge Demo</h1>
2020
window.WVJBCallbacks = [callback];
2121
var WVJBIframe = document.createElement('iframe');
2222
WVJBIframe.style.display = 'none';
23-
WVJBIframe.src = 'http://__bridge_loaded__';
23+
WVJBIframe.src = 'https://__bridge_loaded__';
2424
document.documentElement.appendChild(WVJBIframe);
2525
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
2626
}

README.md

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ WebViewJavascriptBridge
33

44
[![Build Status](https://travis-ci.org/marcuswestin/WebViewJavascriptBridge.svg)](https://travis-ci.org/marcuswestin/WebViewJavascriptBridge)
55

6-
An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews.
6+
An iOS/OSX bridge for sending messages between Obj-C and JavaScript in WKWebViews, UIWebViews & WebViews.
77

88
Who uses WebViewJavascriptBridge?
99
---------------------------------
@@ -62,7 +62,7 @@ Usage
6262
@property WebViewJavascriptBridge* bridge;
6363
```
6464

65-
2) Instantiate WebViewJavascriptBridge with a UIWebView (iOS) or WebView (OSX):
65+
2) Instantiate WebViewJavascriptBridge with a WKWebView, UIWebView (iOS) or WebView (OSX):
6666

6767
```objc
6868
self.bridge = [WebViewJavascriptBridge bridgeForWebView:webView];
@@ -89,7 +89,7 @@ function setupWebViewJavascriptBridge(callback) {
8989
window.WVJBCallbacks = [callback];
9090
var WVJBIframe = document.createElement('iframe');
9191
WVJBIframe.style.display = 'none';
92-
WVJBIframe.src = 'http://__bridge_loaded__';
92+
WVJBIframe.src = 'https://__bridge_loaded__';
9393
document.documentElement.appendChild(WVJBIframe);
9494
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
9595
}
@@ -112,25 +112,6 @@ setupWebViewJavascriptBridge(function(bridge) {
112112
})
113113
```
114114

115-
WKWebView Support (iOS 8+ & OS 10.10+)
116-
--------------------------------------
117-
118-
(WARNING: WKWebView still has [bugs and missing network APIs.](https://github.com/ShingoFukuyama/WKWebViewTips/blob/master/README.md) It may not be a simple drop-in replacement).
119-
120-
WebViewJavascriptBridge supports [WKWebView](http://nshipster.com/wkwebkit/) for iOS 8 and OSX Yosemite. In order to use WKWebView you need to instantiate the `WKWebViewJavascriptBridge`. The rest of the `WKWebViewJavascriptBridge` API is the same as `WebViewJavascriptBridge`.
121-
122-
1) Import the header file:
123-
124-
```objc
125-
#import "WKWebViewJavascriptBridge.h"
126-
```
127-
128-
2) Instantiate WKWebViewJavascriptBridge and with a WKWebView object
129-
130-
```objc
131-
WKWebViewJavascriptBridge* bridge = [WKWebViewJavascriptBridge bridgeForWebView:webView];
132-
```
133-
134115
Automatic reference counting (ARC)
135116
----------------------------------
136117
This library relies on ARC, so if you use ARC in you project, all works fine.
@@ -155,7 +136,7 @@ API Reference
155136

156137
### ObjC API
157138

158-
##### `[WebViewJavascriptBridge bridgeForWebView:(UIWebView/WebView*)webview`
139+
##### `[WebViewJavascriptBridge bridgeForWebView:(WKWebVIew/UIWebView/WebView*)webview`
159140

160141
Create a javascript bridge for the given web view.
161142

@@ -195,9 +176,9 @@ Example:
195176
}];
196177
```
197178
198-
#### `[bridge setWebViewDelegate:(NSObject<UIWebViewDelegate> *)webViewDelegate]`
179+
#### `[bridge setWebViewDelegate:(id)webViewDelegate]`
199180
200-
Optionally, set a `UIWebViewDelegate` if you need to respond to the [web view's lifecycle events](http://developer.apple.com/library/ios/documentation/uikit/reference/UIWebViewDelegate_Protocol/Reference/Reference.html).
181+
Optionally, set a `WKNavigationDelegate/UIWebViewDelegate` if you need to respond to the [web view's lifecycle events](https://developer.apple.com/reference/uikit/uiwebviewdelegate).
201182
202183
##### `[bridge disableJavscriptAlertBoxSafetyTimeout]`
203184

Tests/WebViewJavascriptBridgeTests/BridgeTests.m

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#import <XCTest/XCTest.h>
1010

1111
#import "WebViewJavascriptBridge.h"
12-
#import "WKWebViewJavascriptBridge.h"
1312
#import "AppDelegate.h"
1413

1514
static NSString *const echoHandler = @"echoHandler";
@@ -21,8 +20,7 @@ @interface BridgeTests : XCTestCase
2120
@implementation BridgeTests {
2221
UIWebView *_uiWebView;
2322
WKWebView *_wkWebView;
24-
WebViewJavascriptBridge* _uiWebViewBridge;
25-
WKWebViewJavascriptBridge* _wkWebViewBridge;
23+
NSMutableArray* _bridgeRefs;
2624
}
2725

2826
- (void)setUp {
@@ -38,6 +36,8 @@ - (void)setUp {
3836
_wkWebView = [[WKWebView alloc] initWithFrame:frame];
3937
_wkWebView.backgroundColor = [UIColor redColor];
4038
[rootVC.view addSubview:_wkWebView];
39+
40+
_bridgeRefs = [NSMutableArray array];
4141
}
4242

4343
- (void)tearDown {
@@ -46,14 +46,10 @@ - (void)tearDown {
4646
[_wkWebView removeFromSuperview];
4747
}
4848

49-
- (WebViewJavascriptBridge*)bridgeForCls:(Class)cls webView:(id)webView {
50-
if (cls == [WebViewJavascriptBridge class]) {
51-
_uiWebViewBridge = [WebViewJavascriptBridge bridgeForWebView:webView];
52-
return _uiWebViewBridge;
53-
} else {
54-
_wkWebViewBridge = [WKWebViewJavascriptBridge bridgeForWebView:_wkWebView];
55-
return (WebViewJavascriptBridge*) _wkWebViewBridge;
56-
}
49+
- (WebViewJavascriptBridge*)bridgeForWebView:(id)webView {
50+
WebViewJavascriptBridge* bridge = [WebViewJavascriptBridge bridgeForWebView:webView];
51+
[_bridgeRefs addObject:bridge];
52+
return bridge;
5753
}
5854

5955
static void loadEchoSample(id webView) {
@@ -64,13 +60,13 @@ static void loadEchoSample(id webView) {
6460
const NSTimeInterval timeoutSec = 100;
6561

6662
- (void)testInitialization {
67-
[self classSpecificTestInitialization:[WebViewJavascriptBridge class] webView:_uiWebView];
68-
[self classSpecificTestInitialization:[WKWebViewJavascriptBridge class] webView:_wkWebView];
63+
[self classSpecificTestInitialization:_uiWebView];
64+
[self classSpecificTestInitialization:_wkWebView];
6965
[self waitForExpectationsWithTimeout:timeoutSec handler:NULL];
7066
}
71-
- (void)classSpecificTestInitialization:(Class)cls webView:(id)webView {
67+
- (void)classSpecificTestInitialization:(id)webView {
7268
XCTestExpectation *startup = [self expectationWithDescription:@"Startup completed"];
73-
WebViewJavascriptBridge *bridge = [self bridgeForCls:cls webView:webView];
69+
WebViewJavascriptBridge *bridge = [self bridgeForWebView:webView];
7470
[bridge registerHandler:@"Greet" handler:^(id data, WVJBResponseCallback responseCallback) {
7571
XCTAssertEqualObjects(data, @"Hello world");
7672
[startup fulfill];
@@ -81,12 +77,12 @@ - (void)classSpecificTestInitialization:(Class)cls webView:(id)webView {
8177
}
8278

8379
- (void)testEchoHandler {
84-
[self classSpecificTestEchoHandler:[WebViewJavascriptBridge class] webView:_uiWebView];
85-
[self classSpecificTestEchoHandler:[WKWebViewJavascriptBridge class] webView:_wkWebView];
80+
[self classSpecificTestEchoHandler:_uiWebView];
81+
[self classSpecificTestEchoHandler:_wkWebView];
8682
[self waitForExpectationsWithTimeout:timeoutSec handler:NULL];
8783
}
88-
- (void)classSpecificTestEchoHandler:(Class)cls webView:(id)webView {
89-
WebViewJavascriptBridge *bridge = [self bridgeForCls:cls webView:webView];
84+
- (void)classSpecificTestEchoHandler:(id)webView {
85+
WebViewJavascriptBridge *bridge = [self bridgeForWebView:webView];
9086

9187
XCTestExpectation *callbackInvocked = [self expectationWithDescription:@"Callback invoked"];
9288
[bridge callHandler:echoHandler data:@"testEchoHandler" responseCallback:^(id responseData) {
@@ -98,12 +94,12 @@ - (void)classSpecificTestEchoHandler:(Class)cls webView:(id)webView {
9894
}
9995

10096
- (void)testEchoHandlerAfterSetup {
101-
[self classSpecificTestEchoHandlerAfterSetup:[WebViewJavascriptBridge class] webView:_uiWebView];
102-
[self classSpecificTestEchoHandlerAfterSetup:[WKWebViewJavascriptBridge class] webView:_wkWebView];
97+
[self classSpecificTestEchoHandlerAfterSetup:_uiWebView];
98+
[self classSpecificTestEchoHandlerAfterSetup:_wkWebView];
10399
[self waitForExpectationsWithTimeout:timeoutSec handler:NULL];
104100
}
105-
- (void)classSpecificTestEchoHandlerAfterSetup:(Class)cls webView:(id)webView {
106-
WebViewJavascriptBridge *bridge = [self bridgeForCls:cls webView:webView];
101+
- (void)classSpecificTestEchoHandlerAfterSetup:(id)webView {
102+
WebViewJavascriptBridge *bridge = [self bridgeForWebView:webView];
107103

108104
XCTestExpectation *callbackInvocked = [self expectationWithDescription:@"Callback invoked"];
109105
loadEchoSample(webView);
@@ -116,12 +112,12 @@ - (void)classSpecificTestEchoHandlerAfterSetup:(Class)cls webView:(id)webView {
116112
}
117113

118114
- (void)testObjectEncoding {
119-
[self classSpecificTestObjectEncoding:[WebViewJavascriptBridge class] webView:_uiWebView];
120-
[self classSpecificTestObjectEncoding:[WKWebViewJavascriptBridge class] webView:_wkWebView];
115+
[self classSpecificTestObjectEncoding:_uiWebView];
116+
[self classSpecificTestObjectEncoding:_wkWebView];
121117
[self waitForExpectationsWithTimeout:timeoutSec handler:NULL];
122118
}
123-
- (void)classSpecificTestObjectEncoding:(Class)cls webView:(id)webView {
124-
WebViewJavascriptBridge *bridge = [self bridgeForCls:cls webView:webView];
119+
- (void)classSpecificTestObjectEncoding:(id)webView {
120+
WebViewJavascriptBridge *bridge = [self bridgeForWebView:webView];
125121

126122
void (^echoObject)(id) = ^void(id object) {
127123
XCTestExpectation *callbackInvocked = [self expectationWithDescription:@"Callback invoked"];
@@ -140,12 +136,12 @@ - (void)classSpecificTestObjectEncoding:(Class)cls webView:(id)webView {
140136
}
141137

142138
- (void)testJavascriptReceiveResponse {
143-
[self classSpecificTestJavascriptReceiveResponse:[WebViewJavascriptBridge class] webView:_uiWebView];
144-
[self classSpecificTestJavascriptReceiveResponse:[WKWebViewJavascriptBridge class] webView:_wkWebView];
139+
[self classSpecificTestJavascriptReceiveResponse:_uiWebView];
140+
[self classSpecificTestJavascriptReceiveResponse:_wkWebView];
145141
[self waitForExpectationsWithTimeout:timeoutSec handler:NULL];
146142
}
147-
- (void)classSpecificTestJavascriptReceiveResponse:(Class)cls webView:(id)webView {
148-
WebViewJavascriptBridge *bridge = [self bridgeForCls:cls webView:webView];
143+
- (void)classSpecificTestJavascriptReceiveResponse:(id)webView {
144+
WebViewJavascriptBridge *bridge = [self bridgeForWebView:webView];
149145
loadEchoSample(webView);
150146
XCTestExpectation *callbackInvocked = [self expectationWithDescription:@"Callback invoked"];
151147
[bridge registerHandler:@"objcEchoToJs" handler:^(id data, WVJBResponseCallback responseCallback) {
@@ -158,12 +154,12 @@ - (void)classSpecificTestJavascriptReceiveResponse:(Class)cls webView:(id)webVie
158154
}
159155

160156
- (void)testJavascriptReceiveResponseWithoutSafetyTimeout {
161-
[self classSpecificTestJavascriptReceiveResponseWithoutSafetyTimeout:[WebViewJavascriptBridge class] webView:_uiWebView];
162-
[self classSpecificTestJavascriptReceiveResponseWithoutSafetyTimeout:[WKWebViewJavascriptBridge class] webView:_wkWebView];
157+
[self classSpecificTestJavascriptReceiveResponseWithoutSafetyTimeout:_uiWebView];
158+
[self classSpecificTestJavascriptReceiveResponseWithoutSafetyTimeout:_wkWebView];
163159
[self waitForExpectationsWithTimeout:timeoutSec handler:NULL];
164160
}
165-
- (void)classSpecificTestJavascriptReceiveResponseWithoutSafetyTimeout:(Class)cls webView:(id)webView {
166-
WebViewJavascriptBridge *bridge = [self bridgeForCls:cls webView:webView];
161+
- (void)classSpecificTestJavascriptReceiveResponseWithoutSafetyTimeout:(id)webView {
162+
WebViewJavascriptBridge *bridge = [self bridgeForWebView:webView];
167163
[bridge disableJavscriptAlertBoxSafetyTimeout];
168164
loadEchoSample(webView);
169165
XCTestExpectation *callbackInvocked = [self expectationWithDescription:@"Callback invoked"];

WebViewJavascriptBridge.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ Pod::Spec.new do |s|
1212
s.osx.source_files = 'WebViewJavascriptBridge/*.{h,m}'
1313
s.ios.private_header_files = 'WebViewJavascriptBridge/WebViewJavascriptBridge_JS.h'
1414
s.osx.private_header_files = 'WebViewJavascriptBridge/WebViewJavascriptBridge_JS.h'
15+
s.framework = 'WebKit'
1516
s.ios.framework = 'UIKit'
16-
s.osx.framework = 'WebKit'
1717
end

WebViewJavascriptBridge/WKWebViewJavascriptBridge.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
//
77

88
#if (__MAC_OS_X_VERSION_MAX_ALLOWED > __MAC_10_9 || __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_1)
9-
#define supportsWKWebKit
9+
#define supportsWKWebView
1010
#endif
1111

12-
#if defined(supportsWKWebKit )
12+
#if defined supportsWKWebView
1313

1414
#import <Foundation/Foundation.h>
1515
#import "WebViewJavascriptBridgeBase.h"
@@ -25,7 +25,7 @@
2525
- (void)callHandler:(NSString*)handlerName data:(id)data;
2626
- (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback;
2727
- (void)reset;
28-
- (void)setWebViewDelegate:(id<WKNavigationDelegate>)webViewDelegate;
28+
- (void)setWebViewDelegate:(id)webViewDelegate;
2929
- (void)disableJavscriptAlertBoxSafetyTimeout;
3030

3131
@end

WebViewJavascriptBridge/WKWebViewJavascriptBridge.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
#import "WKWebViewJavascriptBridge.h"
1010

11-
#if defined(supportsWKWebKit)
11+
#if defined supportsWKWebView
1212

1313
@implementation WKWebViewJavascriptBridge {
1414
__weak WKWebView* _webView;

WebViewJavascriptBridge/WebViewJavascriptBridge.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,15 @@
99
#import <Foundation/Foundation.h>
1010
#import "WebViewJavascriptBridgeBase.h"
1111

12+
#if (__MAC_OS_X_VERSION_MAX_ALLOWED > __MAC_10_9 || __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_1)
13+
#define supportsWKWebView
14+
#endif
15+
16+
#if defined supportsWKWebView
17+
#import <WebKit/WebKit.h>
18+
#endif
19+
1220
#if defined __MAC_OS_X_VERSION_MAX_ALLOWED
13-
#import <WebKit/WebKit.h>
1421
#define WVJB_PLATFORM_OSX
1522
#define WVJB_WEBVIEW_TYPE WebView
1623
#define WVJB_WEBVIEW_DELEGATE_TYPE NSObject<WebViewJavascriptBridgeBaseDelegate>
@@ -25,15 +32,17 @@
2532

2633
@interface WebViewJavascriptBridge : WVJB_WEBVIEW_DELEGATE_INTERFACE
2734

28-
+ (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView;
35+
36+
+ (instancetype)bridgeForWebView:(id)webView;
37+
2938
+ (void)enableLogging;
3039
+ (void)setLogMaxLength:(int)length;
3140

3241
- (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler;
3342
- (void)callHandler:(NSString*)handlerName;
3443
- (void)callHandler:(NSString*)handlerName data:(id)data;
3544
- (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback;
36-
- (void)setWebViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate;
45+
- (void)setWebViewDelegate:(id)webViewDelegate;
3746
- (void)disableJavscriptAlertBoxSafetyTimeout;
3847

3948
@end

WebViewJavascriptBridge/WebViewJavascriptBridge.m

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99
#import "WebViewJavascriptBridge.h"
1010

11+
#if defined(supportsWKWebView)
12+
#import "WKWebViewJavascriptBridge.h"
13+
#endif
14+
1115
#if __has_feature(objc_arc_weak)
1216
#define WVJB_WEAK __weak
1317
#else
@@ -31,10 +35,19 @@ + (void)setLogMaxLength:(int)length {
3135
[WebViewJavascriptBridgeBase setLogMaxLength:length];
3236
}
3337

34-
+ (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView {
35-
WebViewJavascriptBridge* bridge = [[self alloc] init];
36-
[bridge _platformSpecificSetup:webView];
37-
return bridge;
38+
+ (instancetype)bridgeForWebView:(id)webView {
39+
#if defined supportsWKWebView
40+
if ([webView isKindOfClass:[WKWebView class]]) {
41+
return (WebViewJavascriptBridge*) [WKWebViewJavascriptBridge bridgeForWebView:webView];
42+
}
43+
#endif
44+
if ([webView isKindOfClass:[WVJB_WEBVIEW_TYPE class]]) {
45+
WebViewJavascriptBridge* bridge = [[self alloc] init];
46+
[bridge _platformSpecificSetup:webView];
47+
return bridge;
48+
}
49+
[NSException raise:@"BadWebViewType" format:@"Unknown web view type."];
50+
return nil;
3851
}
3952

4053
- (void)setWebViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate {

0 commit comments

Comments
 (0)