├── TestPod ├── TestPod │ ├── Assets.xcassets │ │ ├── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── ViewController.h │ ├── SKWebView.h │ ├── ExampleWKWebViewController.h │ ├── AppDelegate.h │ ├── main.m │ ├── SKWebView.m │ ├── ViewController.m │ ├── Info.plist │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── AppDelegate.m │ ├── ExampleWKWebViewController.m │ └── ExampleApp.html ├── Podfile ├── Podfile.lock └── TestPod.xcodeproj │ └── project.pbxproj ├── .gitignore ├── SKJavaScriptBridge ├── WebViewJavascriptLeakAvoider.h ├── WebViewJavascriptLeakAvoider.m ├── WebViewJavascriptBridge.h ├── WebViewJavascriptBridgeBase.h ├── WebViewJavascriptBridgeBase.m └── WebViewJavascriptBridge.m ├── LICENSE ├── README.md └── SKJavaScriptBridge.podspec /TestPod/TestPod/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TestPod/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | platform :ios, "9.0" 3 | target 'TestPod' do 4 | pod 'SKJavaScriptBridge', '~> 1.0.3' 5 | end 6 | -------------------------------------------------------------------------------- /TestPod/TestPod/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // TestPod 4 | // 5 | // Created by 侯森魁 on 2019/10/6. 6 | // Copyright © 2019 侯森魁. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /TestPod/TestPod/SKWebView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SKWebView.h 3 | // TestPod 4 | // 5 | // Created by 侯森魁 on 2020/5/2. 6 | // Copyright © 2020 侯森魁. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface SKWebView : WKWebView 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /TestPod/TestPod/ExampleWKWebViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleWKWebViewController.h 3 | // ExampleApp-iOS 4 | // 5 | // Created by Marcus Westin on 1/13/14. 6 | // Copyright (c) 2014 Marcus Westin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ExampleWKWebViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /TestPod/TestPod/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // TestPod 4 | // 5 | // Created by 侯森魁 on 2019/10/6. 6 | // Copyright © 2019 侯森魁. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /TestPod/TestPod/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TestPod 4 | // 5 | // Created by 侯森魁 on 2019/10/6. 6 | // Copyright © 2019 侯森魁. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TestPod/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - SKJavaScriptBridge (1.0.3) 3 | 4 | DEPENDENCIES: 5 | - SKJavaScriptBridge (~> 1.0.3) 6 | 7 | SPEC REPOS: 8 | https://github.com/CocoaPods/Specs.git: 9 | - SKJavaScriptBridge 10 | 11 | SPEC CHECKSUMS: 12 | SKJavaScriptBridge: 1485c4d7853615a71e55beb3fb662f63e54d0f30 13 | 14 | PODFILE CHECKSUM: 54ade91e276cb994bb82bba79d55928ec16c7113 15 | 16 | COCOAPODS: 1.9.1 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | *.xccheckout 19 | *.xcworkspace 20 | !default.xcworkspace 21 | 22 | #CocoaPods 23 | Pods 24 | !Podfile 25 | !Podfile.lock 26 | -------------------------------------------------------------------------------- /SKJavaScriptBridge/WebViewJavascriptLeakAvoider.h: -------------------------------------------------------------------------------- 1 | // 2 | // LeakAvoider.h 3 | // ExampleApp-iOS 4 | // 5 | // Created by 侯森魁 on 2020/4/20. 6 | // Copyright © 2020 Marcus Westin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface WebViewJavascriptLeakAvoider : NSObject 14 | @property(nonatomic,weak)id delegate; 15 | - (instancetype)initWithDelegate:(id )delegate; 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /TestPod/TestPod/SKWebView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SKWebView.m 3 | // TestPod 4 | // 5 | // Created by 侯森魁 on 2020/5/2. 6 | // Copyright © 2020 侯森魁. All rights reserved. 7 | // 8 | 9 | #import "SKWebView.h" 10 | 11 | @implementation SKWebView 12 | 13 | /* 14 | // Only override drawRect: if you perform custom drawing. 15 | // An empty implementation adversely affects performance during animation. 16 | - (void)drawRect:(CGRect)rect { 17 | // Drawing code 18 | } 19 | */ 20 | /* 21 | I add this class to test whether will lead to memory leak ? 22 | And fix:https://github.com/housenkui/JavascriptBridge/issues/1 23 | 24 | */ 25 | - (void)dealloc { 26 | NSLog(@"SKWebView dealloc "); 27 | } 28 | @end 29 | -------------------------------------------------------------------------------- /SKJavaScriptBridge/WebViewJavascriptLeakAvoider.m: -------------------------------------------------------------------------------- 1 | // 2 | // LeakAvoider.m 3 | // ExampleApp-iOS 4 | // 5 | // Created by 侯森魁 on 2020/4/20. 6 | // Copyright © 2020 Marcus Westin. All rights reserved. 7 | // 8 | 9 | #import "WebViewJavascriptLeakAvoider.h" 10 | 11 | @implementation WebViewJavascriptLeakAvoider 12 | - (instancetype)initWithDelegate:(id )delegate { 13 | if (self = [super init]) { 14 | self.delegate = delegate; 15 | } 16 | return self; 17 | } 18 | - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { 19 | [self.delegate userContentController:userContentController didReceiveScriptMessage:message]; 20 | } 21 | @end 22 | -------------------------------------------------------------------------------- /SKJavaScriptBridge/WebViewJavascriptBridge.h: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewJavascriptBridge.h 3 | // TestPod 4 | // 5 | // Created by 侯森魁 on 2020/4/29. 6 | // Copyright © 2020 侯森魁. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "WebViewJavascriptBridgeBase.h" 11 | #import 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface WebViewJavascriptBridge : NSObject 15 | 16 | + (instancetype)bridgeForWebView:(WKWebView*)webView 17 | showJSconsole:(BOOL)show 18 | enableLogging:(BOOL)enable; 19 | - (void)registerHandler:(NSString*)handlerName handler:(nullable WVJBHandler)handler; 20 | - (void)removeHandler:( NSString* )handlerName; 21 | - (void)callHandler:(NSString*)handlerName; 22 | - (void)callHandler:(NSString*)handlerName data:(nullable id)data; 23 | - (void)callHandler:(NSString*)handlerName data:(nullable id)data responseCallback:(nullable WVJBResponseCallback)responseCallback; 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Daves_Hou 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SKJavaScriptBridge/WebViewJavascriptBridgeBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewJavascriptBridgeBase.h 3 | // TestPod 4 | // 5 | // Created by 侯森魁 on 2020/4/29. 6 | // Copyright © 2020 侯森魁. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | @protocol WebViewJavascriptBridgeBaseDelegate 13 | - (NSString*) _evaluateJavascript:(NSString*)javascriptCommand; 14 | @end 15 | typedef NSDictionary WVJBMessage; 16 | typedef void (^WVJBResponseCallback)(id responseData); 17 | typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); 18 | 19 | @interface WebViewJavascriptBridgeBase : NSObject 20 | @property (weak, nonatomic) id delegate; 21 | @property (strong, nonatomic) NSMutableDictionary* responseCallbacks; 22 | @property (strong, nonatomic) NSMutableDictionary* messageHandlers; 23 | @property (strong, nonatomic) WVJBHandler messageHandler; 24 | 25 | - (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName; 26 | - (void)flushMessageQueue:(NSString *)messageQueueString; 27 | @end 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /TestPod/TestPod/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // TestPod 4 | // 5 | // Created by 侯森魁 on 2019/10/6. 6 | // Copyright © 2019 侯森魁. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "ExampleWKWebViewController.h" 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | self.title = @"first page"; 20 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 21 | [button setTitle:@"click me" forState:UIControlStateNormal]; 22 | [button addTarget:self action:@selector(jump) forControlEvents:UIControlEventTouchUpInside]; 23 | button.frame = CGRectMake(100, 200, 100, 40); 24 | button.center = self.view.center; 25 | self.view.backgroundColor = [UIColor redColor]; 26 | [self.view addSubview:button]; 27 | // Do any additional setup after loading the view. 28 | } 29 | 30 | - (void)jump { 31 | 32 | ExampleWKWebViewController* WKWebViewExampleController = [[ExampleWKWebViewController alloc] init]; 33 | [self.navigationController pushViewController:WKWebViewExampleController animated:YES]; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /TestPod/TestPod/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /TestPod/TestPod/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /TestPod/TestPod/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /TestPod/TestPod/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /TestPod/TestPod/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // TestPod 4 | // 5 | // Created by 侯森魁 on 2019/10/6. 6 | // Copyright © 2019 侯森魁. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "ExampleWKWebViewController.h" 11 | #import "ViewController.h" 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | // Override point for customization after application launch. 21 | 22 | UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:[ViewController new]]; 23 | 24 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 25 | self.window.rootViewController = nav; 26 | [self.window makeKeyAndVisible]; 27 | return YES; 28 | } 29 | 30 | 31 | - (void)applicationWillResignActive:(UIApplication *)application { 32 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 33 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 34 | } 35 | 36 | 37 | - (void)applicationDidEnterBackground:(UIApplication *)application { 38 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 39 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 40 | } 41 | 42 | 43 | - (void)applicationWillEnterForeground:(UIApplication *)application { 44 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 45 | } 46 | 47 | 48 | - (void)applicationDidBecomeActive:(UIApplication *)application { 49 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 50 | } 51 | 52 | 53 | - (void)applicationWillTerminate:(UIApplication *)application { 54 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 55 | } 56 | 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [Please Jump 请使用这个库,它更加完善](https://github.com/SDBridge/SDBridgeOC) to [here](https://github.com/SDBridge/SDBridgeOC). 2 | 3 | 4 | WebViewJavascriptBridge 5 | ======================= 6 | 7 | An iOS/OSX bridge for sending messages between Obj-C and JavaScript in WKWebViews. Also easy to get js console.log. 8 | 9 | More simple more light. Refactor WebViewJavascriptBridge with AOP 10 | ========================== 11 | 12 | How to use ? 13 | ========================== 14 | 15 | ### Installation with CocoaPods 16 | Add this to your [podfile](https://guides.cocoapods.org/using/getting-started.html) and run `pod install` to install: 17 | 18 | ```ruby 19 | pod 'SKJavaScriptBridge', '~> 1.0.3' 20 | ``` 21 | If you can't find the last version, maybe you need to update local pod repo. 22 | ```ruby 23 | pod repo update 24 | ``` 25 | 26 | ### Manual installation 27 | Drag the `WebViewJavascriptBridge` folder into your project. 28 | 29 | In the dialog that appears, uncheck "Copy items into destination group's folder" and select "Create groups for any folders". 30 | 31 | Usage 32 | ----- 33 | 1) Import the header file and declare an ivar property: 34 | 35 | ```objc 36 | #import "WebViewJavascriptBridge.h" 37 | ``` 38 | ```objc 39 | @property (nonatomic, strong) WKWebView *webView; 40 | @property (nonatomic, strong) WebViewJavascriptBridge* bridge; 41 | ``` 42 | 43 | ```objc 44 | self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds]; 45 | [self.view addSubview:self.webView]; 46 | if(!_bridge){ 47 | _bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView 48 | showJSconsole:YES 49 | enableLogging:YES]; 50 | } 51 | ``` 52 | 53 | 2) Register a handler in ObjC, and call a JS handler: 54 | 55 | ```objc 56 | [_bridge registerHandler:@"ObjC Echo" handler:^(id data, WVJBResponseCallback responseCallback) { 57 | NSLog(@"ObjC Echo called with: %@", data); 58 | responseCallback(data); 59 | }]; 60 | [_bridge callHandler:@"JS Echo" data:nil responseCallback:^(id responseData) { 61 | NSLog(@"ObjC received response: %@", responseData); 62 | }]; 63 | ``` 64 | 3) Copy and paste `setupWebViewJavascriptBridge` into your JS: 65 | 66 | ```javascript 67 | function setupWebViewJavascriptBridge(callback) { 68 | return callback(WebViewJavascriptBridge); 69 | } 70 | ``` 71 | 5) Finally, call `setupWebViewJavascriptBridge` and then use the bridge to register handlers and call ObjC handlers: 72 | 73 | ```javascript 74 | setupWebViewJavascriptBridge(function(bridge) { 75 | 76 | /* Initialize your app here */ 77 | 78 | bridge.registerHandler('JS Echo', function(data, responseCallback) { 79 | console.log("JS Echo called with:", data) 80 | responseCallback(data) 81 | }) 82 | bridge.callHandler('ObjC Echo', {'key':'value'}, function responseCallback(responseData) { 83 | console.log("JS received response:", responseData) 84 | }) 85 | }) 86 | ``` 87 | -------------------------------------------------------------------------------- /TestPod/TestPod/ExampleWKWebViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleWKWebViewController.m 3 | // ExampleApp-iOS 4 | // 5 | // Created by Marcus Westin on 1/13/14. 6 | // Copyright (c) 2014 Marcus Westin. All rights reserved. 7 | // 8 | 9 | #import "ExampleWKWebViewController.h" 10 | #import "WebViewJavascriptBridge.h" 11 | #import "SKWebView.h" 12 | @interface ExampleWKWebViewController () 13 | @property (nonatomic, strong) SKWebView *webView; 14 | @property (nonatomic, strong) WebViewJavascriptBridge* bridge; 15 | @end 16 | 17 | @implementation ExampleWKWebViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | 22 | self.webView = [[SKWebView alloc] initWithFrame:self.view.bounds]; 23 | [self.view addSubview:self.webView]; 24 | if(!_bridge){ 25 | _bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView 26 | showJSconsole:YES 27 | enableLogging:YES]; 28 | } 29 | [_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { 30 | NSLog(@"testObjcCallback called: %@", data); 31 | responseCallback(@"Response from testObjcCallback"); 32 | }]; 33 | [self renderButtons:self.webView]; 34 | [self loadExamplePage:self.webView]; 35 | } 36 | 37 | - (void)callHandler:(id)sender { 38 | id data = @{ @"greetingFromObjC": @"Hi there, JS!" }; 39 | [_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) { 40 | NSLog(@"testJavascriptHandler responded: %@", response); 41 | }]; 42 | } 43 | 44 | - (void)renderButtons:(WKWebView*)webView { 45 | UIFont* font = [UIFont fontWithName:@"HelveticaNeue" size:12.0]; 46 | 47 | UIButton *callbackButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 48 | [callbackButton setTitle:@"Call handler" forState:UIControlStateNormal]; 49 | [callbackButton addTarget:self action:@selector(callHandler:) forControlEvents:UIControlEventTouchUpInside]; 50 | [self.view insertSubview:callbackButton aboveSubview:webView]; 51 | callbackButton.frame = CGRectMake(10, 400, 100, 35); 52 | callbackButton.titleLabel.font = font; 53 | 54 | UIButton* reloadButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 55 | [reloadButton setTitle:@"Reload webview" forState:UIControlStateNormal]; 56 | [reloadButton addTarget:webView action:@selector(reload) forControlEvents:UIControlEventTouchUpInside]; 57 | [self.view insertSubview:reloadButton aboveSubview:webView]; 58 | reloadButton.frame = CGRectMake(110, 400, 100, 35); 59 | reloadButton.titleLabel.font = font; 60 | } 61 | 62 | - (void)loadExamplePage:(WKWebView*)webView { 63 | NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"]; 64 | NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; 65 | NSURL *baseURL = [NSURL fileURLWithPath:htmlPath]; 66 | [webView loadHTMLString:appHtml baseURL:baseURL]; 67 | } 68 | -(void)viewDidDisappear:(BOOL)animated { 69 | [super viewDidDisappear:animated]; 70 | NSLog(@"viewDidDisappear "); 71 | } 72 | 73 | -(void)dealloc { 74 | NSLog(@"ExampleWKWebViewController dealloc"); 75 | } 76 | @end 77 | -------------------------------------------------------------------------------- /TestPod/TestPod/ExampleApp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 |

WebViewJavascriptBridge Demo

12 | 72 |
73 | 74 | -------------------------------------------------------------------------------- /SKJavaScriptBridge/WebViewJavascriptBridgeBase.m: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewJavascriptBridgeBase.m 3 | // TestPod 4 | // 5 | // Created by 侯森魁 on 2020/4/29. 6 | // Copyright © 2020 侯森魁. All rights reserved. 7 | // 8 | 9 | #import "WebViewJavascriptBridgeBase.h" 10 | @implementation WebViewJavascriptBridgeBase { 11 | long _uniqueId; 12 | } 13 | - (instancetype)init { 14 | if (self = [super init]) { 15 | self.messageHandlers = [NSMutableDictionary dictionary]; 16 | self.responseCallbacks = [NSMutableDictionary dictionary]; 17 | _uniqueId = 0; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName { 23 | NSMutableDictionary* message = [NSMutableDictionary dictionary]; 24 | 25 | if (data) { 26 | message[@"data"] = data; 27 | } 28 | 29 | if (responseCallback) { 30 | NSString* callbackId = [NSString stringWithFormat:@"objc_cb_%ld", ++_uniqueId]; 31 | self.responseCallbacks[callbackId] = [responseCallback copy]; 32 | message[@"callbackId"] = callbackId; 33 | } 34 | 35 | if (handlerName) { 36 | message[@"handlerName"] = handlerName; 37 | } 38 | [self _dispatchMessage:message]; 39 | } 40 | 41 | - (void)flushMessageQueue:(NSString *)messageQueueString{ 42 | if (messageQueueString == nil || messageQueueString.length == 0) { 43 | NSLog(@"WebViewJavascriptBridge: WARNING: ObjC got nil while fetching the message queue JSON from webview. This can happen if the WebViewJavascriptBridge JS is not currently present in the webview, e.g if the webview just loaded a new page."); 44 | return; 45 | } 46 | 47 | id messages = [self _deserializeMessageJSON:messageQueueString]; 48 | for (WVJBMessage* message in messages) { 49 | if (![message isKindOfClass:[WVJBMessage class]]) { 50 | NSLog(@"WebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [message class], message); 51 | continue; 52 | } 53 | NSString* responseId = message[@"responseId"]; 54 | if (responseId) { 55 | WVJBResponseCallback responseCallback = _responseCallbacks[responseId]; 56 | responseCallback(message[@"responseData"]); 57 | [self.responseCallbacks removeObjectForKey:responseId]; 58 | } else { 59 | WVJBResponseCallback responseCallback = NULL; 60 | NSString* callbackId = message[@"callbackId"]; 61 | if (callbackId) { 62 | responseCallback = ^(id responseData) { 63 | if (responseData == nil) { 64 | responseData = [NSNull null]; 65 | } 66 | 67 | WVJBMessage* msg = @{ @"responseId":callbackId, @"responseData":responseData }; 68 | [self _dispatchMessage:msg]; 69 | }; 70 | } else { 71 | responseCallback = ^(id ignoreResponseData) { 72 | // Do nothing 73 | }; 74 | } 75 | 76 | WVJBHandler handler = self.messageHandlers[message[@"handlerName"]]; 77 | 78 | if (!handler) { 79 | NSLog(@"WVJBNoHandlerException, No handler for message from JS: %@", message); 80 | continue; 81 | } 82 | 83 | handler(message[@"data"], responseCallback); 84 | } 85 | } 86 | } 87 | 88 | - (NSString *)_serializeMessage:(id)message pretty:(BOOL)pretty{ 89 | return [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:message options:(NSJSONWritingOptions)(pretty ? NSJSONWritingPrettyPrinted : 0) error:nil] encoding:NSUTF8StringEncoding]; 90 | } 91 | 92 | - (NSArray*)_deserializeMessageJSON:(NSString *)messageJSON { 93 | return [NSJSONSerialization JSONObjectWithData:[messageJSON dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil]; 94 | } 95 | 96 | - (void) _evaluateJavascript:(NSString *)javascriptCommand { 97 | [self.delegate _evaluateJavascript:javascriptCommand]; 98 | } 99 | 100 | - (void)_dispatchMessage:(WVJBMessage*)message { 101 | NSString *messageJSON = [self _serializeMessage:message pretty:NO]; 102 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; 103 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; 104 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\'" withString:@"\\\'"]; 105 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]; 106 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"]; 107 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\f" withString:@"\\f"]; 108 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\u2028" withString:@"\\u2028"]; 109 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\u2029" withString:@"\\u2029"]; 110 | 111 | NSString* javascriptCommand = [NSString stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON]; 112 | if ([[NSThread currentThread] isMainThread]) { 113 | [self _evaluateJavascript:javascriptCommand]; 114 | 115 | } else { 116 | dispatch_sync(dispatch_get_main_queue(), ^{ 117 | [self _evaluateJavascript:javascriptCommand]; 118 | }); 119 | } 120 | } 121 | 122 | @end 123 | -------------------------------------------------------------------------------- /SKJavaScriptBridge.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint SKJavascriptBridge.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | 11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 12 | # 13 | # These will help people to find your library, and whilst it 14 | # can feel like a chore to fill in it's definitely to your advantage. The 15 | # summary should be tweet-length, and the description more in depth. 16 | # 17 | 18 | s.name = "SKJavaScriptBridge" 19 | s.version = "1.0.3" 20 | s.summary = "More simple more light more easy to use for iOS/OSX bridge with Javascript. Also can get js console.log ~" 21 | 22 | # This description is used to generate tags and improve search results. 23 | # * Think: What does it do? Why did you write it? What is the focus? 24 | # * Try to keep it short, snappy and to the point. 25 | # * Write the description between the DESC delimiters below. 26 | # * Finally, don't worry about the indent, CocoaPods strips it! 27 | s.description = <<-DESC 28 | English:More simple more light more easy to use for iOS/OSX bridge with Javascript. 29 | Chinese :更简单、更轻、更易使用的原生和 JavaScript框架. 30 | DESC 31 | 32 | s.homepage = "https://github.com/housenkui/JavaScriptBridge" 33 | # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" 34 | 35 | 36 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 37 | # 38 | # Licensing your code is important. See http://choosealicense.com for more info. 39 | # CocoaPods will detect a license file if there is a named LICENSE* 40 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. 41 | # 42 | 43 | s.license = "MIT" 44 | # s.license = { :type => "MIT", :file => "FILE_LICENSE" } 45 | 46 | 47 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 48 | # 49 | # Specify the authors of the library, with email addresses. Email addresses 50 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also 51 | # accepts just a name if you'd rather not provide an email address. 52 | # 53 | # Specify a social_media_url where others can refer to, for example a twitter 54 | # profile URL. 55 | # 56 | 57 | s.author = { "侯森魁" => "840737320@qq.com" } 58 | # Or just: s.author = "侯森魁" 59 | # s.authors = { "侯森魁" => "housenkui@gmail.com" } 60 | # s.social_media_url = "http://twitter.com/侯森魁" 61 | 62 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 63 | # 64 | # If this Pod runs only on iOS or OS X, then specify the platform and 65 | # the deployment target. You can optionally include the target after the platform. 66 | # 67 | 68 | # s.platform = :ios 69 | # s.platform = :ios, "5.0" 70 | 71 | # When using multiple platforms 72 | s.ios.deployment_target = "8.0" 73 | s.osx.deployment_target = "10.10" 74 | # s.watchos.deployment_target = "2.0" 75 | # s.tvos.deployment_target = "9.0" 76 | 77 | 78 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 79 | # 80 | # Specify the location from where the source should be retrieved. 81 | # Supports git, hg, bzr, svn and HTTP. 82 | # 83 | 84 | s.source = { :git => "https://github.com/housenkui/JavaScriptBridge.git", :tag => "#{s.version}" } 85 | 86 | 87 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 88 | # 89 | # CocoaPods is smart about how it includes source code. For source files 90 | # giving a folder will include any swift, h, m, mm, c & cpp files. 91 | # For header files it will include any header in the folder. 92 | # Not including the public_header_files will make all headers public. 93 | # 94 | 95 | s.source_files = "SKJavaScriptBridge" 96 | # s.exclude_files = "Classes/Exclude" 97 | 98 | # s.public_header_files = "Classes/**/*.h" 99 | 100 | 101 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 102 | # 103 | # A list of resources included with the Pod. These are copied into the 104 | # target bundle with a build phase script. Anything else will be cleaned. 105 | # You can preserve files from being cleaned, please don't preserve 106 | # non-essential files like tests, examples and documentation. 107 | # 108 | 109 | # s.resource = "icon.png" 110 | # s.resources = "Resources/*.png" 111 | 112 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave" 113 | 114 | 115 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 116 | # 117 | # Link your library with frameworks, or libraries. Libraries do not include 118 | # the lib prefix of their name. 119 | # 120 | 121 | s.framework = "WebKit" 122 | # s.frameworks = "SomeFramework", "AnotherFramework" 123 | 124 | # s.library = "iconv" 125 | # s.libraries = "iconv", "xml2" 126 | 127 | 128 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 129 | # 130 | # If your library depends on compiler flags you can set them in the xcconfig hash 131 | # where they will only apply to your library. If you depend on other Podspecs 132 | # you can include multiple dependencies to ensure it works. 133 | 134 | s.requires_arc = true 135 | 136 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } 137 | # s.dependency "JSONKit", "~> 1.4" 138 | 139 | end 140 | -------------------------------------------------------------------------------- /SKJavaScriptBridge/WebViewJavascriptBridge.m: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewJavascriptBridge.m 3 | // TestPod 4 | // 5 | // Created by 侯森魁 on 2020/4/29. 6 | // Copyright © 2020 侯森魁. All rights reserved. 7 | // 8 | 9 | #import "WebViewJavascriptBridge.h" 10 | #import "WebViewJavascriptLeakAvoider.h" 11 | #define kBridgePrefix @"__bridge__" 12 | 13 | @implementation WebViewJavascriptBridge { 14 | WKWebView* _webView; 15 | long _uniqueId; 16 | WebViewJavascriptBridgeBase *_base; 17 | BOOL _showJSconsole; 18 | BOOL _enableLogging; 19 | } 20 | 21 | + (instancetype)bridgeForWebView:(WKWebView*)webView 22 | showJSconsole:(BOOL)show 23 | enableLogging:(BOOL)enable { 24 | WebViewJavascriptBridge* bridge = [[self alloc] init]; 25 | [bridge _setupInstance:webView showJSconsole:show enableLogging:enable]; 26 | return bridge; 27 | } 28 | 29 | - (void)callHandler:(NSString *)handlerName { 30 | [self callHandler:handlerName data:nil responseCallback:nil]; 31 | } 32 | 33 | - (void)callHandler:(NSString *)handlerName data:(id)data { 34 | [self callHandler:handlerName data:data responseCallback:nil]; 35 | } 36 | 37 | - (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback { 38 | [_base sendData:data responseCallback:responseCallback handlerName:handlerName]; 39 | } 40 | 41 | - (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { 42 | _base.messageHandlers[handlerName] = [handler copy]; 43 | } 44 | 45 | - (void)removeHandler:(NSString *)handlerName { 46 | [_base.messageHandlers removeObjectForKey:handlerName]; 47 | } 48 | 49 | 50 | - (void)_setupInstance:(WKWebView*)webView showJSconsole:(BOOL)show enableLogging:(BOOL)enable{ 51 | _webView = webView; 52 | _base = [[WebViewJavascriptBridgeBase alloc] init]; 53 | _base.delegate = self; 54 | _showJSconsole = show; 55 | _enableLogging = enable; 56 | 57 | [self addScriptMessageHandler]; 58 | [self _injectJavascriptFile]; 59 | } 60 | - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { 61 | NSString * body = (NSString * )message.body; 62 | if ([self _filterMessage:body]) { 63 | NSMutableString *mstr = [NSMutableString stringWithString:body]; 64 | [mstr replaceOccurrencesOfString:kBridgePrefix withString:@"" options:0 range:NSMakeRange(0, 10)]; 65 | [_base flushMessageQueue:mstr]; 66 | } 67 | } 68 | - (void)_injectJavascriptFile { 69 | NSString *bridge_js = WebViewJavascriptBridge_js(); 70 | //injected the method when H5 starts to create the DOM tree 71 | WKUserScript * bridge_userScript = [[WKUserScript alloc]initWithSource:bridge_js injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; 72 | [_webView.configuration.userContentController addUserScript:bridge_userScript]; 73 | if (_showJSconsole) { 74 | NSString *console_log_js = WebViewJavascriptBridge_console_log_js(); 75 | WKUserScript * console_log_userScript = [[WKUserScript alloc]initWithSource:console_log_js injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; 76 | [_webView.configuration.userContentController addUserScript:console_log_userScript]; 77 | } 78 | } 79 | - (void) addScriptMessageHandler { 80 | [_webView.configuration.userContentController addScriptMessageHandler:[[WebViewJavascriptLeakAvoider alloc]initWithDelegate:self] name:@"pipe"]; 81 | } 82 | 83 | - (void)removeScriptMessageHandler { 84 | [_webView.configuration.userContentController removeScriptMessageHandlerForName:@"pipe"]; 85 | } 86 | 87 | - (NSString*) _evaluateJavascript:(NSString*)javascriptCommand { 88 | [_webView evaluateJavaScript:javascriptCommand completionHandler:nil]; 89 | return NULL; 90 | } 91 | 92 | - (NSString *)_filterMessage:(NSString *) message { 93 | if (_enableLogging) { 94 | NSLog(@"All WVJB RCVD:%@",message); 95 | } 96 | if (message&& [message isKindOfClass:[NSString class]] && [message containsString:kBridgePrefix]) 97 | { 98 | return message; 99 | } 100 | return nil; 101 | } 102 | 103 | - (void)dealloc { 104 | [self removeScriptMessageHandler]; 105 | } 106 | 107 | NSString * WebViewJavascriptBridge_js() { 108 | #define __WVJB_js_func__(x) #x 109 | 110 | // BEGIN preprocessorJSCode 111 | static NSString * preprocessorJSCode = @__WVJB_js_func__( 112 | ;(function(window) { 113 | 114 | window.WebViewJavascriptBridge = { 115 | registerHandler: registerHandler, 116 | callHandler: callHandler, 117 | _handleMessageFromObjC: _handleMessageFromObjC 118 | }; 119 | 120 | var sendMessageQueue = []; 121 | var messageHandlers = {}; 122 | var responseCallbacks = {}; 123 | var uniqueId = 1; 124 | 125 | function registerHandler(handlerName, handler) { 126 | messageHandlers[handlerName] = handler; 127 | } 128 | 129 | function callHandler(handlerName, data, responseCallback) { 130 | if (arguments.length === 2 && typeof data == 'function') { 131 | responseCallback = data; 132 | data = null; 133 | } 134 | _doSend({ handlerName:handlerName, data:data }, responseCallback); 135 | } 136 | function _doSend(message, responseCallback) { 137 | if (responseCallback) { 138 | var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime(); 139 | responseCallbacks[callbackId] = responseCallback; 140 | message['callbackId'] = callbackId; 141 | } 142 | sendMessageQueue.push(message); 143 | window.webkit.messageHandlers.pipe.postMessage('__bridge__'+ JSON.stringify(sendMessageQueue)); 144 | sendMessageQueue = []; 145 | } 146 | 147 | function _dispatchMessageFromObjC(messageJSON) { 148 | _doDispatchMessageFromObjC(); 149 | 150 | function _doDispatchMessageFromObjC() { 151 | var message = JSON.parse(messageJSON); 152 | var messageHandler; 153 | var responseCallback; 154 | 155 | if (message.responseId) { 156 | responseCallback = responseCallbacks[message.responseId]; 157 | if (!responseCallback) { 158 | 159 | return; 160 | } 161 | 162 | responseCallback(message.responseData); 163 | delete responseCallbacks[message.responseId]; 164 | } else { 165 | if (message.callbackId) { 166 | var callbackResponseId = message.callbackId; 167 | responseCallback = function(responseData) { 168 | _doSend({ handlerName:message.handlerName, responseId:callbackResponseId, responseData:responseData }); 169 | }; 170 | } 171 | var handler = messageHandlers[message.handlerName]; 172 | if (!handler) { 173 | console.log("WebViewJavascriptBridge: WARNING: no handler for message from ObjC:", message); 174 | } else { 175 | handler(message.data, responseCallback); 176 | } 177 | } 178 | } 179 | } 180 | function _handleMessageFromObjC(messageJSON) { 181 | _dispatchMessageFromObjC(messageJSON); 182 | } 183 | })(window); 184 | ); // END preprocessorJSCode 185 | 186 | #undef __WVJB_js_func__ 187 | return preprocessorJSCode; 188 | }; 189 | 190 | NSString * WebViewJavascriptBridge_console_log_js() { 191 | #define __WVJB_js_func__(x) #x 192 | 193 | // BEGIN preprocessorJSCode 194 | static NSString * preprocessorJSCode = @__WVJB_js_func__( 195 | ;(function(window) { 196 | let printObject = function (obj) { 197 | let output = ""; 198 | if (obj === null) { 199 | output += "null"; 200 | } 201 | else if (typeof(obj) == "undefined") { 202 | output += "undefined"; 203 | } 204 | else if (typeof obj ==='object'){ 205 | output+="{"; 206 | for(let key in obj){ 207 | let value = obj[key]; 208 | output+= "\""+key+"\""+":"+"\""+value+"\""+","; 209 | } 210 | output = output.substr(0, output.length - 1); 211 | output+="}"; 212 | } 213 | else { 214 | output = "" + obj; 215 | } 216 | return output; 217 | }; 218 | window.console.log = (function (oriLogFunc,printObject) { 219 | return function (str) { 220 | str = printObject(str); 221 | window.webkit.messageHandlers.pipe.postMessage(str); 222 | oriLogFunc.call(window.console, str); 223 | } 224 | })(window.console.log,printObject); 225 | 226 | })(window); 227 | ); // END preprocessorJSCode 228 | 229 | #undef __WVJB_js_func__ 230 | return preprocessorJSCode; 231 | }; 232 | 233 | @end 234 | -------------------------------------------------------------------------------- /TestPod/TestPod.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5AD61B33D366E2ADF93E156D /* libPods-TestPod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9E387BAA3859F867FBE51F20 /* libPods-TestPod.a */; }; 11 | EF5D0B37245D3D72008DC69C /* SKWebView.m in Sources */ = {isa = PBXBuildFile; fileRef = EF5D0B36245D3D72008DC69C /* SKWebView.m */; }; 12 | EFB7D6BB2349C17900BC5118 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EFB7D6BA2349C17900BC5118 /* AppDelegate.m */; }; 13 | EFB7D6BE2349C17900BC5118 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EFB7D6BD2349C17900BC5118 /* ViewController.m */; }; 14 | EFB7D6C12349C17900BC5118 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EFB7D6BF2349C17900BC5118 /* Main.storyboard */; }; 15 | EFB7D6C32349C17A00BC5118 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EFB7D6C22349C17A00BC5118 /* Assets.xcassets */; }; 16 | EFB7D6C62349C17A00BC5118 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EFB7D6C42349C17A00BC5118 /* LaunchScreen.storyboard */; }; 17 | EFB7D6C92349C17A00BC5118 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = EFB7D6C82349C17A00BC5118 /* main.m */; }; 18 | EFB7D6D12349C26D00BC5118 /* ExampleWKWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EFB7D6CF2349C26D00BC5118 /* ExampleWKWebViewController.m */; }; 19 | EFB7D6D32349C27E00BC5118 /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = EFB7D6D22349C27E00BC5118 /* ExampleApp.html */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 5CC0B8CF36CF0645BB9D6142 /* Pods-TestPod.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TestPod.release.xcconfig"; path = "Target Support Files/Pods-TestPod/Pods-TestPod.release.xcconfig"; sourceTree = ""; }; 24 | 921F3C61CD9EF49A32E71133 /* Pods-TestPod.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TestPod.debug.xcconfig"; path = "Target Support Files/Pods-TestPod/Pods-TestPod.debug.xcconfig"; sourceTree = ""; }; 25 | 9E387BAA3859F867FBE51F20 /* libPods-TestPod.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-TestPod.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | EF05866A2441E0F400FD174D /* libavdevice.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libavdevice.dylib; path = "../../../../ffmpeg/代码/FFmpeg/FFmpeg/libs/libavdevice.dylib"; sourceTree = ""; }; 27 | EF05866B2441E0F400FD174D /* libavformat.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libavformat.dylib; path = "../../../../ffmpeg/代码/FFmpeg/FFmpeg/libs/libavformat.dylib"; sourceTree = ""; }; 28 | EF05866C2441E0F400FD174D /* libavutil.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libavutil.dylib; path = "../../../../ffmpeg/代码/FFmpeg/FFmpeg/libs/libavutil.dylib"; sourceTree = ""; }; 29 | EF5D0B35245D3D72008DC69C /* SKWebView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SKWebView.h; sourceTree = ""; }; 30 | EF5D0B36245D3D72008DC69C /* SKWebView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SKWebView.m; sourceTree = ""; }; 31 | EFB7D6B62349C17900BC5118 /* TestPod.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestPod.app; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | EFB7D6B92349C17900BC5118 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 33 | EFB7D6BA2349C17900BC5118 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 34 | EFB7D6BC2349C17900BC5118 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 35 | EFB7D6BD2349C17900BC5118 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 36 | EFB7D6C02349C17900BC5118 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 37 | EFB7D6C22349C17A00BC5118 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 38 | EFB7D6C52349C17A00BC5118 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 39 | EFB7D6C72349C17A00BC5118 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | EFB7D6C82349C17A00BC5118 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 41 | EFB7D6CF2349C26D00BC5118 /* ExampleWKWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleWKWebViewController.m; sourceTree = ""; }; 42 | EFB7D6D02349C26D00BC5118 /* ExampleWKWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleWKWebViewController.h; sourceTree = ""; }; 43 | EFB7D6D22349C27E00BC5118 /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = ""; }; 44 | /* End PBXFileReference section */ 45 | 46 | /* Begin PBXFrameworksBuildPhase section */ 47 | EFB7D6B32349C17900BC5118 /* Frameworks */ = { 48 | isa = PBXFrameworksBuildPhase; 49 | buildActionMask = 2147483647; 50 | files = ( 51 | 5AD61B33D366E2ADF93E156D /* libPods-TestPod.a in Frameworks */, 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 2F155DE595AB7F8E0E4734BD /* Pods */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 921F3C61CD9EF49A32E71133 /* Pods-TestPod.debug.xcconfig */, 62 | 5CC0B8CF36CF0645BB9D6142 /* Pods-TestPod.release.xcconfig */, 63 | ); 64 | path = Pods; 65 | sourceTree = ""; 66 | }; 67 | DE20228B789579007F72D496 /* Frameworks */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | EF05866A2441E0F400FD174D /* libavdevice.dylib */, 71 | EF05866B2441E0F400FD174D /* libavformat.dylib */, 72 | EF05866C2441E0F400FD174D /* libavutil.dylib */, 73 | 9E387BAA3859F867FBE51F20 /* libPods-TestPod.a */, 74 | ); 75 | name = Frameworks; 76 | sourceTree = ""; 77 | }; 78 | EFB7D6AD2349C17900BC5118 = { 79 | isa = PBXGroup; 80 | children = ( 81 | EFB7D6B82349C17900BC5118 /* TestPod */, 82 | EFB7D6B72349C17900BC5118 /* Products */, 83 | 2F155DE595AB7F8E0E4734BD /* Pods */, 84 | DE20228B789579007F72D496 /* Frameworks */, 85 | ); 86 | sourceTree = ""; 87 | }; 88 | EFB7D6B72349C17900BC5118 /* Products */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | EFB7D6B62349C17900BC5118 /* TestPod.app */, 92 | ); 93 | name = Products; 94 | sourceTree = ""; 95 | }; 96 | EFB7D6B82349C17900BC5118 /* TestPod */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | EFB7D6D22349C27E00BC5118 /* ExampleApp.html */, 100 | EFB7D6B92349C17900BC5118 /* AppDelegate.h */, 101 | EFB7D6BA2349C17900BC5118 /* AppDelegate.m */, 102 | EFB7D6BC2349C17900BC5118 /* ViewController.h */, 103 | EFB7D6BD2349C17900BC5118 /* ViewController.m */, 104 | EFB7D6D02349C26D00BC5118 /* ExampleWKWebViewController.h */, 105 | EFB7D6CF2349C26D00BC5118 /* ExampleWKWebViewController.m */, 106 | EF5D0B35245D3D72008DC69C /* SKWebView.h */, 107 | EF5D0B36245D3D72008DC69C /* SKWebView.m */, 108 | EFB7D6BF2349C17900BC5118 /* Main.storyboard */, 109 | EFB7D6C22349C17A00BC5118 /* Assets.xcassets */, 110 | EFB7D6C42349C17A00BC5118 /* LaunchScreen.storyboard */, 111 | EFB7D6C72349C17A00BC5118 /* Info.plist */, 112 | EFB7D6C82349C17A00BC5118 /* main.m */, 113 | ); 114 | path = TestPod; 115 | sourceTree = ""; 116 | }; 117 | /* End PBXGroup section */ 118 | 119 | /* Begin PBXNativeTarget section */ 120 | EFB7D6B52349C17900BC5118 /* TestPod */ = { 121 | isa = PBXNativeTarget; 122 | buildConfigurationList = EFB7D6CC2349C17A00BC5118 /* Build configuration list for PBXNativeTarget "TestPod" */; 123 | buildPhases = ( 124 | 19CBCD9DE7636863BD18ECA6 /* [CP] Check Pods Manifest.lock */, 125 | EFB7D6B22349C17900BC5118 /* Sources */, 126 | EFB7D6B32349C17900BC5118 /* Frameworks */, 127 | EFB7D6B42349C17900BC5118 /* Resources */, 128 | ); 129 | buildRules = ( 130 | ); 131 | dependencies = ( 132 | ); 133 | name = TestPod; 134 | productName = TestPod; 135 | productReference = EFB7D6B62349C17900BC5118 /* TestPod.app */; 136 | productType = "com.apple.product-type.application"; 137 | }; 138 | /* End PBXNativeTarget section */ 139 | 140 | /* Begin PBXProject section */ 141 | EFB7D6AE2349C17900BC5118 /* Project object */ = { 142 | isa = PBXProject; 143 | attributes = { 144 | LastUpgradeCheck = 1030; 145 | ORGANIZATIONNAME = "侯森魁"; 146 | TargetAttributes = { 147 | EFB7D6B52349C17900BC5118 = { 148 | CreatedOnToolsVersion = 10.3; 149 | }; 150 | }; 151 | }; 152 | buildConfigurationList = EFB7D6B12349C17900BC5118 /* Build configuration list for PBXProject "TestPod" */; 153 | compatibilityVersion = "Xcode 9.3"; 154 | developmentRegion = en; 155 | hasScannedForEncodings = 0; 156 | knownRegions = ( 157 | en, 158 | Base, 159 | ); 160 | mainGroup = EFB7D6AD2349C17900BC5118; 161 | productRefGroup = EFB7D6B72349C17900BC5118 /* Products */; 162 | projectDirPath = ""; 163 | projectRoot = ""; 164 | targets = ( 165 | EFB7D6B52349C17900BC5118 /* TestPod */, 166 | ); 167 | }; 168 | /* End PBXProject section */ 169 | 170 | /* Begin PBXResourcesBuildPhase section */ 171 | EFB7D6B42349C17900BC5118 /* Resources */ = { 172 | isa = PBXResourcesBuildPhase; 173 | buildActionMask = 2147483647; 174 | files = ( 175 | EFB7D6C62349C17A00BC5118 /* LaunchScreen.storyboard in Resources */, 176 | EFB7D6C32349C17A00BC5118 /* Assets.xcassets in Resources */, 177 | EFB7D6C12349C17900BC5118 /* Main.storyboard in Resources */, 178 | EFB7D6D32349C27E00BC5118 /* ExampleApp.html in Resources */, 179 | ); 180 | runOnlyForDeploymentPostprocessing = 0; 181 | }; 182 | /* End PBXResourcesBuildPhase section */ 183 | 184 | /* Begin PBXShellScriptBuildPhase section */ 185 | 19CBCD9DE7636863BD18ECA6 /* [CP] Check Pods Manifest.lock */ = { 186 | isa = PBXShellScriptBuildPhase; 187 | buildActionMask = 2147483647; 188 | files = ( 189 | ); 190 | inputFileListPaths = ( 191 | ); 192 | inputPaths = ( 193 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 194 | "${PODS_ROOT}/Manifest.lock", 195 | ); 196 | name = "[CP] Check Pods Manifest.lock"; 197 | outputFileListPaths = ( 198 | ); 199 | outputPaths = ( 200 | "$(DERIVED_FILE_DIR)/Pods-TestPod-checkManifestLockResult.txt", 201 | ); 202 | runOnlyForDeploymentPostprocessing = 0; 203 | shellPath = /bin/sh; 204 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 205 | showEnvVarsInLog = 0; 206 | }; 207 | /* End PBXShellScriptBuildPhase section */ 208 | 209 | /* Begin PBXSourcesBuildPhase section */ 210 | EFB7D6B22349C17900BC5118 /* Sources */ = { 211 | isa = PBXSourcesBuildPhase; 212 | buildActionMask = 2147483647; 213 | files = ( 214 | EFB7D6BE2349C17900BC5118 /* ViewController.m in Sources */, 215 | EFB7D6C92349C17A00BC5118 /* main.m in Sources */, 216 | EFB7D6D12349C26D00BC5118 /* ExampleWKWebViewController.m in Sources */, 217 | EFB7D6BB2349C17900BC5118 /* AppDelegate.m in Sources */, 218 | EF5D0B37245D3D72008DC69C /* SKWebView.m in Sources */, 219 | ); 220 | runOnlyForDeploymentPostprocessing = 0; 221 | }; 222 | /* End PBXSourcesBuildPhase section */ 223 | 224 | /* Begin PBXVariantGroup section */ 225 | EFB7D6BF2349C17900BC5118 /* Main.storyboard */ = { 226 | isa = PBXVariantGroup; 227 | children = ( 228 | EFB7D6C02349C17900BC5118 /* Base */, 229 | ); 230 | name = Main.storyboard; 231 | sourceTree = ""; 232 | }; 233 | EFB7D6C42349C17A00BC5118 /* LaunchScreen.storyboard */ = { 234 | isa = PBXVariantGroup; 235 | children = ( 236 | EFB7D6C52349C17A00BC5118 /* Base */, 237 | ); 238 | name = LaunchScreen.storyboard; 239 | sourceTree = ""; 240 | }; 241 | /* End PBXVariantGroup section */ 242 | 243 | /* Begin XCBuildConfiguration section */ 244 | EFB7D6CA2349C17A00BC5118 /* Debug */ = { 245 | isa = XCBuildConfiguration; 246 | buildSettings = { 247 | ALWAYS_SEARCH_USER_PATHS = NO; 248 | CLANG_ANALYZER_NONNULL = YES; 249 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 250 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 251 | CLANG_CXX_LIBRARY = "libc++"; 252 | CLANG_ENABLE_MODULES = YES; 253 | CLANG_ENABLE_OBJC_ARC = YES; 254 | CLANG_ENABLE_OBJC_WEAK = YES; 255 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 256 | CLANG_WARN_BOOL_CONVERSION = YES; 257 | CLANG_WARN_COMMA = YES; 258 | CLANG_WARN_CONSTANT_CONVERSION = YES; 259 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 260 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 261 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 262 | CLANG_WARN_EMPTY_BODY = YES; 263 | CLANG_WARN_ENUM_CONVERSION = YES; 264 | CLANG_WARN_INFINITE_RECURSION = YES; 265 | CLANG_WARN_INT_CONVERSION = YES; 266 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 267 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 268 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 269 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 270 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 271 | CLANG_WARN_STRICT_PROTOTYPES = YES; 272 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 273 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 274 | CLANG_WARN_UNREACHABLE_CODE = YES; 275 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 276 | CODE_SIGN_IDENTITY = "iPhone Developer"; 277 | COPY_PHASE_STRIP = NO; 278 | DEBUG_INFORMATION_FORMAT = dwarf; 279 | ENABLE_STRICT_OBJC_MSGSEND = YES; 280 | ENABLE_TESTABILITY = YES; 281 | GCC_C_LANGUAGE_STANDARD = gnu11; 282 | GCC_DYNAMIC_NO_PIC = NO; 283 | GCC_NO_COMMON_BLOCKS = YES; 284 | GCC_OPTIMIZATION_LEVEL = 0; 285 | GCC_PREPROCESSOR_DEFINITIONS = ( 286 | "DEBUG=1", 287 | "$(inherited)", 288 | ); 289 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 290 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 291 | GCC_WARN_UNDECLARED_SELECTOR = YES; 292 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 293 | GCC_WARN_UNUSED_FUNCTION = YES; 294 | GCC_WARN_UNUSED_VARIABLE = YES; 295 | IPHONEOS_DEPLOYMENT_TARGET = 12.4; 296 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 297 | MTL_FAST_MATH = YES; 298 | ONLY_ACTIVE_ARCH = YES; 299 | SDKROOT = iphoneos; 300 | }; 301 | name = Debug; 302 | }; 303 | EFB7D6CB2349C17A00BC5118 /* Release */ = { 304 | isa = XCBuildConfiguration; 305 | buildSettings = { 306 | ALWAYS_SEARCH_USER_PATHS = NO; 307 | CLANG_ANALYZER_NONNULL = YES; 308 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 309 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 310 | CLANG_CXX_LIBRARY = "libc++"; 311 | CLANG_ENABLE_MODULES = YES; 312 | CLANG_ENABLE_OBJC_ARC = YES; 313 | CLANG_ENABLE_OBJC_WEAK = YES; 314 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 315 | CLANG_WARN_BOOL_CONVERSION = YES; 316 | CLANG_WARN_COMMA = YES; 317 | CLANG_WARN_CONSTANT_CONVERSION = YES; 318 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 319 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 320 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 321 | CLANG_WARN_EMPTY_BODY = YES; 322 | CLANG_WARN_ENUM_CONVERSION = YES; 323 | CLANG_WARN_INFINITE_RECURSION = YES; 324 | CLANG_WARN_INT_CONVERSION = YES; 325 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 326 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 327 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 328 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 329 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 330 | CLANG_WARN_STRICT_PROTOTYPES = YES; 331 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 332 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 333 | CLANG_WARN_UNREACHABLE_CODE = YES; 334 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 335 | CODE_SIGN_IDENTITY = "iPhone Developer"; 336 | COPY_PHASE_STRIP = NO; 337 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 338 | ENABLE_NS_ASSERTIONS = NO; 339 | ENABLE_STRICT_OBJC_MSGSEND = YES; 340 | GCC_C_LANGUAGE_STANDARD = gnu11; 341 | GCC_NO_COMMON_BLOCKS = YES; 342 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 343 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 344 | GCC_WARN_UNDECLARED_SELECTOR = YES; 345 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 346 | GCC_WARN_UNUSED_FUNCTION = YES; 347 | GCC_WARN_UNUSED_VARIABLE = YES; 348 | IPHONEOS_DEPLOYMENT_TARGET = 12.4; 349 | MTL_ENABLE_DEBUG_INFO = NO; 350 | MTL_FAST_MATH = YES; 351 | SDKROOT = iphoneos; 352 | VALIDATE_PRODUCT = YES; 353 | }; 354 | name = Release; 355 | }; 356 | EFB7D6CD2349C17A00BC5118 /* Debug */ = { 357 | isa = XCBuildConfiguration; 358 | baseConfigurationReference = 921F3C61CD9EF49A32E71133 /* Pods-TestPod.debug.xcconfig */; 359 | buildSettings = { 360 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 361 | CODE_SIGN_STYLE = Automatic; 362 | DEVELOPMENT_TEAM = D9DMY5ZV46; 363 | INFOPLIST_FILE = TestPod/Info.plist; 364 | LD_RUNPATH_SEARCH_PATHS = ( 365 | "$(inherited)", 366 | "@executable_path/Frameworks", 367 | ); 368 | PRODUCT_BUNDLE_IDENTIFIER = test.TestPod; 369 | PRODUCT_NAME = "$(TARGET_NAME)"; 370 | TARGETED_DEVICE_FAMILY = "1,2"; 371 | }; 372 | name = Debug; 373 | }; 374 | EFB7D6CE2349C17A00BC5118 /* Release */ = { 375 | isa = XCBuildConfiguration; 376 | baseConfigurationReference = 5CC0B8CF36CF0645BB9D6142 /* Pods-TestPod.release.xcconfig */; 377 | buildSettings = { 378 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 379 | CODE_SIGN_STYLE = Automatic; 380 | DEVELOPMENT_TEAM = D9DMY5ZV46; 381 | INFOPLIST_FILE = TestPod/Info.plist; 382 | LD_RUNPATH_SEARCH_PATHS = ( 383 | "$(inherited)", 384 | "@executable_path/Frameworks", 385 | ); 386 | PRODUCT_BUNDLE_IDENTIFIER = test.TestPod; 387 | PRODUCT_NAME = "$(TARGET_NAME)"; 388 | TARGETED_DEVICE_FAMILY = "1,2"; 389 | }; 390 | name = Release; 391 | }; 392 | /* End XCBuildConfiguration section */ 393 | 394 | /* Begin XCConfigurationList section */ 395 | EFB7D6B12349C17900BC5118 /* Build configuration list for PBXProject "TestPod" */ = { 396 | isa = XCConfigurationList; 397 | buildConfigurations = ( 398 | EFB7D6CA2349C17A00BC5118 /* Debug */, 399 | EFB7D6CB2349C17A00BC5118 /* Release */, 400 | ); 401 | defaultConfigurationIsVisible = 0; 402 | defaultConfigurationName = Release; 403 | }; 404 | EFB7D6CC2349C17A00BC5118 /* Build configuration list for PBXNativeTarget "TestPod" */ = { 405 | isa = XCConfigurationList; 406 | buildConfigurations = ( 407 | EFB7D6CD2349C17A00BC5118 /* Debug */, 408 | EFB7D6CE2349C17A00BC5118 /* Release */, 409 | ); 410 | defaultConfigurationIsVisible = 0; 411 | defaultConfigurationName = Release; 412 | }; 413 | /* End XCConfigurationList section */ 414 | }; 415 | rootObject = EFB7D6AE2349C17900BC5118 /* Project object */; 416 | } 417 | --------------------------------------------------------------------------------