├── CHANGELOG.md
├── Assets
├── backbutton.png
├── backbutton@2x.png
├── backbutton@3x.png
├── forwardbutton.png
├── forwardbutton@2x.png
└── forwardbutton@3x.png
├── ExampleProject
├── KINWebBrowserExample
│ ├── en.lproj
│ │ └── InfoPlist.strings
│ ├── main.m
│ ├── KINWebBrowserExample-Prefix.pch
│ ├── Images.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── LaunchImage.launchimage
│ │ │ └── Contents.json
│ ├── KINAppDelegate.h
│ ├── KINWebBrowserExample-Info.plist
│ ├── KINWebBrowserExampleViewController.h
│ ├── KINWebBrowserExampleViewController.xib
│ ├── KINAppDelegate.m
│ └── KINWebBrowserExampleViewController.m
├── KINWebBrowserExampleTests
│ ├── en.lproj
│ │ └── InfoPlist.strings
│ ├── KINWebBrowserExampleTests-Info.plist
│ └── KINWebBrowserExampleTests.m
├── Podfile
├── KINWebBrowserExample.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── project.pbxproj
└── KINWebBrowserExample.xcworkspace
│ └── contents.xcworkspacedata
├── .gitignore
├── KINWebBrowser.podspec
├── LICENSE
├── README.md
└── KINWebBrowser
├── KINWebBrowserViewController.h
└── KINWebBrowserViewController.m
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # KINWebBrowser CHANGELOG
2 |
3 | ## 0.1.0
4 |
5 | Initial release.
6 |
--------------------------------------------------------------------------------
/Assets/backbutton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dfmuir/KINWebBrowser/HEAD/Assets/backbutton.png
--------------------------------------------------------------------------------
/Assets/backbutton@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dfmuir/KINWebBrowser/HEAD/Assets/backbutton@2x.png
--------------------------------------------------------------------------------
/Assets/backbutton@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dfmuir/KINWebBrowser/HEAD/Assets/backbutton@3x.png
--------------------------------------------------------------------------------
/Assets/forwardbutton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dfmuir/KINWebBrowser/HEAD/Assets/forwardbutton.png
--------------------------------------------------------------------------------
/Assets/forwardbutton@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dfmuir/KINWebBrowser/HEAD/Assets/forwardbutton@2x.png
--------------------------------------------------------------------------------
/Assets/forwardbutton@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dfmuir/KINWebBrowser/HEAD/Assets/forwardbutton@3x.png
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExample/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExampleTests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/ExampleProject/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/CocoaPods/Specs.git'
2 |
3 | xcodeproj 'KINWebBrowserExample.xcodeproj'
4 | platform :ios, :deployment_target => '7.0'
5 |
6 | pod 'KINWebBrowser'
7 |
8 |
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExample.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.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 |
20 | #CocoaPods
21 | Pods
22 | Podfile.lock
23 | Rakefile
24 |
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExample/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // KINWebBrowserExample
4 | //
5 | // Created by David Muir on 2/4/14.
6 | // Copyright (c) 2014 Kinwa, Inc. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "KINAppDelegate.h"
12 |
13 | int main(int argc, char * argv[])
14 | {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([KINAppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExample/KINWebBrowserExample-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header
3 | //
4 | // The contents of this file are implicitly included at the beginning of every source file.
5 | //
6 |
7 | #import
8 |
9 | #ifndef __IPHONE_3_0
10 | #warning "This project uses features only available in iOS SDK 3.0 and later."
11 | #endif
12 |
13 | #ifdef __OBJC__
14 | #import
15 | #import
16 | #endif
17 |
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExampleTests/KINWebBrowserExampleTests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | com.kinwa.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExampleTests/KINWebBrowserExampleTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // KINWebBrowserExampleTests.m
3 | // KINWebBrowserExampleTests
4 | //
5 | // Created by David Muir on 2/4/14.
6 | // Copyright (c) 2014 Kinwa, Inc. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface KINWebBrowserExampleTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation KINWebBrowserExampleTests
16 |
17 | - (void)setUp
18 | {
19 | [super setUp];
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 | }
22 |
23 | - (void)tearDown
24 | {
25 | // Put teardown code here. This method is called after the invocation of each test method in the class.
26 | [super tearDown];
27 | }
28 |
29 | - (void)testExample
30 | {
31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
32 | }
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/KINWebBrowser.podspec:
--------------------------------------------------------------------------------
1 |
2 | Pod::Spec.new do |s|
3 |
4 | s.name = "KINWebBrowser"
5 | s.version = "1.3.2"
6 | s.summary = "A web browser module for your apps."
7 | s.description = <<-DESC
8 | KINWebBrowser is a web browser module for your apps. Powered by WKWebView on iOS 8. Backwards compatible with iOS 7 using UIWebView. KINWebBrowser offers the simplest way to add a web browser to your apps.
9 | DESC
10 |
11 | s.homepage = "https://github.com/dfmuir/KINWebBrowser"
12 | s.license = { :type => 'MIT', :file => 'LICENSE' }
13 | s.author = { "David F. Muir V" => "dfmuir@gmail.com" }
14 | s.platform = :ios, '7.0'
15 | s.source = { :git => "https://github.com/dfmuir/KINWebBrowser.git", :tag => s.version.to_s }
16 | s.source_files = 'KINWebBrowser', 'KINWebBrowser/**/*.{h,m}'
17 | s.resources = "Assets/*.png"
18 | s.requires_arc = true
19 |
20 | s.weak_framework = 'WebKit'
21 |
22 | s.dependency 'TUSafariActivity', '1.0.4'
23 | s.dependency 'ARChromeActivity', '1.0.5'
24 |
25 | end
26 |
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExample/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "40x40",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "60x60",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "60x60",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "ipad",
25 | "size" : "29x29",
26 | "scale" : "1x"
27 | },
28 | {
29 | "idiom" : "ipad",
30 | "size" : "29x29",
31 | "scale" : "2x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "40x40",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "40x40",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "76x76",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "76x76",
51 | "scale" : "2x"
52 | }
53 | ],
54 | "info" : {
55 | "version" : 1,
56 | "author" : "xcode"
57 | }
58 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | KINWebBrowser
2 |
3 | Created by David F. Muir V
4 | dfmuir@gmail.com
5 | Co-Founder & Engineer at Kinwa, Inc.
6 | http://www.kinwa.co
7 |
8 | The MIT License (MIT)
9 |
10 | Copyright (c) 2014 David Muir
11 |
12 | Permission is hereby granted, free of charge, to any person obtaining a copy of
13 | this software and associated documentation files (the "Software"), to deal in
14 | the Software without restriction, including without limitation the rights to
15 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
16 | the Software, and to permit persons to whom the Software is furnished to do so,
17 | subject to the following conditions:
18 |
19 | The above copyright notice and this permission notice shall be included in all
20 | copies or substantial portions of the Software.
21 |
22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
25 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
26 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 |
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExample/Images.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "orientation" : "portrait",
5 | "idiom" : "iphone",
6 | "extent" : "full-screen",
7 | "minimum-system-version" : "7.0",
8 | "scale" : "2x"
9 | },
10 | {
11 | "orientation" : "portrait",
12 | "idiom" : "iphone",
13 | "subtype" : "retina4",
14 | "extent" : "full-screen",
15 | "minimum-system-version" : "7.0",
16 | "scale" : "2x"
17 | },
18 | {
19 | "orientation" : "portrait",
20 | "idiom" : "ipad",
21 | "extent" : "full-screen",
22 | "minimum-system-version" : "7.0",
23 | "scale" : "1x"
24 | },
25 | {
26 | "orientation" : "landscape",
27 | "idiom" : "ipad",
28 | "extent" : "full-screen",
29 | "minimum-system-version" : "7.0",
30 | "scale" : "1x"
31 | },
32 | {
33 | "orientation" : "portrait",
34 | "idiom" : "ipad",
35 | "extent" : "full-screen",
36 | "minimum-system-version" : "7.0",
37 | "scale" : "2x"
38 | },
39 | {
40 | "orientation" : "landscape",
41 | "idiom" : "ipad",
42 | "extent" : "full-screen",
43 | "minimum-system-version" : "7.0",
44 | "scale" : "2x"
45 | }
46 | ],
47 | "info" : {
48 | "version" : 1,
49 | "author" : "xcode"
50 | }
51 | }
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExample/KINAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // KINAppDelegate.h
3 | //
4 | // KINWebBrowser
5 | //
6 | // Created by David F. Muir V
7 | // dfmuir@gmail.com
8 | // Co-Founder & Engineer at Kinwa, Inc.
9 | // http://www.kinwa.co
10 | //
11 | // The MIT License (MIT)
12 | //
13 | // Copyright (c) 2014 David Muir
14 | //
15 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
16 | // this software and associated documentation files (the "Software"), to deal in
17 | // the Software without restriction, including without limitation the rights to
18 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
19 | // the Software, and to permit persons to whom the Software is furnished to do so,
20 | // subject to the following conditions:
21 | //
22 | // The above copyright notice and this permission notice shall be included in all
23 | // copies or substantial portions of the Software.
24 | //
25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
27 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
28 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
29 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 | //
32 |
33 |
34 | #import
35 |
36 | @interface KINAppDelegate : UIResponder
37 |
38 | @property (strong, nonatomic) UIWindow *window;
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExample/KINWebBrowserExample-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | com.kinwa.${PRODUCT_NAME:rfc1034identifier}
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0
25 | LSRequiresIPhoneOS
26 |
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 |
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExample/KINWebBrowserExampleViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // KINWebBrowserExampleViewController.m
3 | //
4 | // KINWebBrowser
5 | //
6 | // Created by David F. Muir V
7 | // dfmuir@gmail.com
8 | // Co-Founder & Engineer at Kinwa, Inc.
9 | // http://www.kinwa.co
10 | //
11 | // The MIT License (MIT)
12 | //
13 | // Copyright (c) 2014 David Muir
14 | //
15 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
16 | // this software and associated documentation files (the "Software"), to deal in
17 | // the Software without restriction, including without limitation the rights to
18 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
19 | // the Software, and to permit persons to whom the Software is furnished to do so,
20 | // subject to the following conditions:
21 | //
22 | // The above copyright notice and this permission notice shall be included in all
23 | // copies or substantial portions of the Software.
24 | //
25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
27 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
28 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
29 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 | //
32 |
33 |
34 | #import
35 |
36 | #import
37 |
38 | @interface KINWebBrowserExampleViewController : UIViewController
39 |
40 | - (IBAction)pushButtonPressed:(id)sender;
41 | - (IBAction)presentButtonPressed:(id)sender;
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExample/KINWebBrowserExampleViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
28 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExample/KINAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // KINAppDelegate.m
3 | //
4 | // KINWebBrowser
5 | //
6 | // Created by David F. Muir V
7 | // dfmuir@gmail.com
8 | // Co-Founder & Engineer at Kinwa, Inc.
9 | // http://www.kinwa.co
10 | //
11 | // The MIT License (MIT)
12 | //
13 | // Copyright (c) 2014 David Muir
14 | //
15 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
16 | // this software and associated documentation files (the "Software"), to deal in
17 | // the Software without restriction, including without limitation the rights to
18 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
19 | // the Software, and to permit persons to whom the Software is furnished to do so,
20 | // subject to the following conditions:
21 | //
22 | // The above copyright notice and this permission notice shall be included in all
23 | // copies or substantial portions of the Software.
24 | //
25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
27 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
28 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
29 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 | //
32 |
33 |
34 | #import "KINAppDelegate.h"
35 |
36 | #import "KINWebBrowserExampleViewController.h"
37 |
38 | @implementation KINAppDelegate
39 |
40 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
41 | {
42 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
43 | // Override point for customization after application launch.
44 |
45 | KINWebBrowserExampleViewController *viewController = [[KINWebBrowserExampleViewController alloc] init];
46 |
47 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
48 |
49 | [self.window setRootViewController:navigationController];
50 | self.window.backgroundColor = [UIColor whiteColor];
51 | [self.window makeKeyAndVisible];
52 | return YES;
53 | }
54 |
55 | - (void)applicationWillResignActive:(UIApplication *)application
56 | {
57 | // 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.
58 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
59 | }
60 |
61 | - (void)applicationDidEnterBackground:(UIApplication *)application
62 | {
63 | // 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.
64 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
65 | }
66 |
67 | - (void)applicationWillEnterForeground:(UIApplication *)application
68 | {
69 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
70 | }
71 |
72 | - (void)applicationDidBecomeActive:(UIApplication *)application
73 | {
74 | // 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.
75 | }
76 |
77 | - (void)applicationWillTerminate:(UIApplication *)application
78 | {
79 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
80 | }
81 |
82 | @end
83 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | KINWebBrowser
2 | ==========
3 |
4 | KINWebBrowser is a web browser module for your apps.
5 |
6 | Powered by [WKWebView](https://developer.apple.com/library/IOs/documentation/WebKit/Reference/WKWebView_Ref/index.html) on iOS 8. Backwards compatible with iOS 7 using [UIWebView](https://developer.apple.com/library/ios/documentation/Uikit/reference/UIWebView_Class/index.html).
7 |
8 | 
9 |
10 | Features
11 | ------------------------
12 | * iOS 7 & 8 support for iPhone and iPad devices
13 | * Safari-like interface
14 | * Animated progress bar
15 | * Customizable UI including tint color
16 | * Portrait and landscape orientation support
17 | * Use with existing UINavigationController or present modally
18 | * Delegate protocol for status callbacks
19 | * Action button to allow users to copy URL, share, or open in Safari & Google Chrome
20 | * Supports subclassing
21 | * Installation with [CocoaPods](http://cocoapods.org/)
22 |
23 | Overview
24 | ------------------------
25 | KINWebBrowser consists of a single component:
26 |
27 | **`KINWebBrowserViewController`** - a `UIViewController` that contains a full featured web browser.
28 |
29 | *`KINWebBrowserViewController` must be contained in a UINavigationController.*
30 |
31 | **Pushing to the navigation stack:**
32 | ```objective-c
33 | KINWebBrowserViewController *webBrowser = [KINWebBrowserViewController webBrowser];
34 | [self.navigationController pushViewController:webBrowser animated:YES];
35 | [webBrowser loadURLString:@"http://www.example.com"];
36 | ```
37 |
38 | **Presenting Modally:**
39 | ```objective-c
40 | UINavigationController *webBrowserNavigationController = [KINWebBrowserViewController navigationControllerWithWebBrowser];
41 | [self presentViewController:webBrowserNavigationController animated:YES completion:nil];
42 |
43 | KINWebBrowserViewController *webBrowser = [webBrowserNavigationController rootWebBrowser];
44 | [webBrowser loadURLString:@"http://www.example.com"];
45 | ```
46 |
47 | Installation
48 | ------------------------
49 |
50 | #### CocoaPods
51 | [CocoaPods](http://cocoapods.org) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries in your projects. See the ["Getting Started" for more information](http://guides.cocoapods.org/using/getting-started.html).
52 |
53 | ###### Podfile
54 |
55 | ```ruby
56 | platform :ios, '7.0'
57 | pod 'KINWebBrowser'
58 | ```
59 |
60 | Dependencies
61 | ------------------------
62 | These dependency projects should be also installed with KINWebBrowser. They are installed automatically when installing KINWebBrowser with CocoaPods.
63 |
64 | * [TUSafariActivity](https://github.com/davbeck/TUSafariActivity) - a UIActivity subclass that provides an "Open In Safari" action to a UIActivityViewController
65 | * [ARChromeActivity](https://github.com/alextrob/ARChromeActivity) - a UIActivity subclass that provides an "Open In Google Chrome" action to a UIActivityViewController
66 |
67 |
68 | Customizing the User Interface
69 | ------------------------
70 |
71 | **Tint Color**
72 |
73 | The tint color of the toolbars and toolbar items can be customized.
74 |
75 | ```
76 | webBrowser.tintColor = [UIColor blueColor];
77 | webBrowser.barTintColor = [UIColor blackColor];
78 | ```
79 |
80 | **Title Bar Content**
81 |
82 | The URL can be shown in the `UINavigationBar` while loading. The title of the page can be shown when loading completes.
83 | ```
84 | webBrowser.showsURLInNavigationBar = NO;
85 | webBrowser.showsPageTitleInNavigationBar = YES;
86 | ```
87 |
88 |
89 | Implementing `KINWebBrowserDelegate` Protocol
90 | ------------------------
91 | `KINWebBrowserDelegate` is a set of `@optional` callback methods to inform the `delegate` of status changes.
92 |
93 | ```
94 | - (void)webBrowser:(KINWebBrowserViewController *)webBrowser didStartLoadingURL:(NSURL *)URL;
95 | - (void)webBrowser:(KINWebBrowserViewController *)webBrowser didFinishLoadingURL:(NSURL *)URL;
96 | - (void)webBrowser:(KINWebBrowserViewController *)webBrowser didFailToLoadURL:(NSURL *)URL withError:(NSError *)error;
97 | ```
98 |
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExample/KINWebBrowserExampleViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // KINWebBrowserExampleViewController.m
3 | //
4 | // KINWebBrowser
5 | //
6 | // Created by David F. Muir V
7 | // dfmuir@gmail.com
8 | // Co-Founder & Engineer at Kinwa, Inc.
9 | // http://www.kinwa.co
10 | //
11 | // The MIT License (MIT)
12 | //
13 | // Copyright (c) 2014 David Muir
14 | //
15 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
16 | // this software and associated documentation files (the "Software"), to deal in
17 | // the Software without restriction, including without limitation the rights to
18 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
19 | // the Software, and to permit persons to whom the Software is furnished to do so,
20 | // subject to the following conditions:
21 | //
22 | // The above copyright notice and this permission notice shall be included in all
23 | // copies or substantial portions of the Software.
24 | //
25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
27 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
28 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
29 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 | //
32 |
33 |
34 | #import "KINWebBrowserExampleViewController.h"
35 |
36 |
37 | @interface KINWebBrowserExampleViewController ()
38 |
39 | @end
40 |
41 | static NSString *const defaultAddress = @"https://www.apple.com";
42 |
43 | @implementation KINWebBrowserExampleViewController
44 |
45 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
46 | {
47 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
48 | if (self) {
49 | // Custom initialization
50 | }
51 | return self;
52 | }
53 |
54 | - (void)viewDidLoad
55 | {
56 | [super viewDidLoad];
57 | // Do any additional setup after loading the view from its nib.
58 |
59 | self.navigationItem.title = @"";
60 |
61 | [self.navigationController setToolbarHidden:YES];
62 | [self.navigationController setNavigationBarHidden:YES];
63 |
64 | self.navigationController.navigationBar.translucent = YES;
65 | self.navigationController.toolbar.translucent = YES;
66 |
67 |
68 | }
69 |
70 | - (void)didReceiveMemoryWarning
71 | {
72 | [super didReceiveMemoryWarning];
73 | // Dispose of any resources that can be recreated.
74 | }
75 |
76 | #pragma mark - KINWebBrowserDelegate Protocol Implementation
77 |
78 | - (void)webBrowser:(KINWebBrowserViewController *)webBrowser didStartLoadingURL:(NSURL *)URL {
79 | NSLog(@"Started Loading URL : %@", URL);
80 | }
81 |
82 | - (void)webBrowser:(KINWebBrowserViewController *)webBrowser didFinishLoadingURL:(NSURL *)URL {
83 | NSLog(@"Finished Loading URL : %@", URL);
84 | }
85 |
86 | - (void)webBrowser:(KINWebBrowserViewController *)webBrowser didFailToLoadURL:(NSURL *)URL withError:(NSError *)error {
87 | NSLog(@"Failed To Load URL : %@ With Error: %@", URL, error);
88 | }
89 |
90 | - (void)webBrowserViewControllerWillDismiss:(KINWebBrowserViewController*)viewController {
91 | NSLog(@"View Controller will dismiss: %@", viewController);
92 |
93 | }
94 |
95 |
96 | #pragma mark - IBActions
97 |
98 | - (IBAction)pushButtonPressed:(id)sender {
99 | KINWebBrowserViewController *webBrowser = [KINWebBrowserViewController webBrowser];
100 | [webBrowser setDelegate:self];
101 | [self.navigationController pushViewController:webBrowser animated:YES];
102 | [webBrowser loadURLString:defaultAddress];
103 | }
104 |
105 | - (IBAction)presentButtonPressed:(id)sender {
106 | UINavigationController *webBrowserNavigationController = [KINWebBrowserViewController navigationControllerWithWebBrowser];
107 | KINWebBrowserViewController *webBrowser = [webBrowserNavigationController rootWebBrowser];
108 | [webBrowser setDelegate:self];
109 | webBrowser.showsURLInNavigationBar = YES;
110 | webBrowser.tintColor = [UIColor whiteColor];
111 | webBrowser.barTintColor = [UIColor colorWithRed:102.0f/255.0f green:204.0f/255.0f blue:51.0f/255.0f alpha:1.0f];
112 | webBrowser.showsPageTitleInNavigationBar = NO;
113 | webBrowser.showsURLInNavigationBar = NO;
114 | [self presentViewController:webBrowserNavigationController animated:YES completion:nil];
115 |
116 | [webBrowser loadURLString:defaultAddress];
117 | }
118 | @end
119 |
--------------------------------------------------------------------------------
/KINWebBrowser/KINWebBrowserViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // KINWebBrowserViewController.h
3 | //
4 | // KINWebBrowser
5 | //
6 | // Created by David F. Muir V
7 | // dfmuir@gmail.com
8 | // Co-Founder & Engineer at Kinwa, Inc.
9 | // http://www.kinwa.co
10 | //
11 | // The MIT License (MIT)
12 | //
13 | // Copyright (c) 2014 David Muir
14 | //
15 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
16 | // this software and associated documentation files (the "Software"), to deal in
17 | // the Software without restriction, including without limitation the rights to
18 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
19 | // the Software, and to permit persons to whom the Software is furnished to do so,
20 | // subject to the following conditions:
21 | //
22 | // The above copyright notice and this permission notice shall be included in all
23 | // copies or substantial portions of the Software.
24 | //
25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
27 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
28 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
29 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 | //
32 |
33 | #import
34 | #import
35 |
36 | @class KINWebBrowserViewController;
37 |
38 | /*
39 |
40 | UINavigationController+KINWebBrowserWrapper category enables access to casted KINWebBroswerViewController when set as rootViewController of UINavigationController
41 |
42 | */
43 | @interface UINavigationController(KINWebBrowser)
44 |
45 | // Returns rootViewController casted as KINWebBrowserViewController
46 | - (KINWebBrowserViewController *)rootWebBrowser;
47 |
48 | @end
49 |
50 |
51 |
52 | @protocol KINWebBrowserDelegate
53 | @optional
54 | - (void)webBrowser:(KINWebBrowserViewController *)webBrowser didStartLoadingURL:(NSURL *)URL;
55 | - (void)webBrowser:(KINWebBrowserViewController *)webBrowser didFinishLoadingURL:(NSURL *)URL;
56 | - (void)webBrowser:(KINWebBrowserViewController *)webBrowser didFailToLoadURL:(NSURL *)URL error:(NSError *)error;
57 | - (void)webBrowserViewControllerWillDismiss:(KINWebBrowserViewController*)viewController;
58 | @end
59 |
60 |
61 | /*
62 |
63 | KINWebBrowserViewController is designed to be used inside of a UINavigationController.
64 | For convenience, two sets of static initializers are available.
65 |
66 | */
67 | @interface KINWebBrowserViewController : UIViewController
68 |
69 | #pragma mark - Public Properties
70 |
71 | @property (nonatomic, weak) id delegate;
72 |
73 | // The main and only UIProgressView
74 | @property (nonatomic, strong) UIProgressView *progressView;
75 |
76 | // The web views
77 | // Depending on the version of iOS, one of these will be set
78 | @property (nonatomic, strong) WKWebView *wkWebView;
79 | @property (nonatomic, strong) UIWebView *uiWebView;
80 |
81 | - (id)initWithConfiguration:(WKWebViewConfiguration *)configuration NS_AVAILABLE_IOS(8_0);
82 |
83 | #pragma mark - Static Initializers
84 |
85 | /*
86 | Initialize a basic KINWebBrowserViewController instance for push onto navigation stack
87 |
88 | Ideal for use with UINavigationController pushViewController:animated: or initWithRootViewController:
89 |
90 | Optionally specify KINWebBrowser options or WKWebConfiguration
91 | */
92 |
93 | + (KINWebBrowserViewController *)webBrowser;
94 | + (KINWebBrowserViewController *)webBrowserWithConfiguration:(WKWebViewConfiguration *)configuration NS_AVAILABLE_IOS(8_0);
95 |
96 | /*
97 | Initialize a UINavigationController with a KINWebBrowserViewController for modal presentation.
98 |
99 | Ideal for use with presentViewController:animated:
100 |
101 | Optionally specify KINWebBrowser options or WKWebConfiguration
102 | */
103 |
104 | + (UINavigationController *)navigationControllerWithWebBrowser;
105 | + (UINavigationController *)navigationControllerWithWebBrowserWithConfiguration:(WKWebViewConfiguration *)configuration NS_AVAILABLE_IOS(8_0);
106 |
107 |
108 | @property (nonatomic, strong) UIBarButtonItem *actionButton;
109 | @property (nonatomic, strong) UIColor *tintColor;
110 | @property (nonatomic, strong) UIColor *barTintColor;
111 | @property (nonatomic, assign) BOOL actionButtonHidden;
112 | @property (nonatomic, assign) BOOL showsURLInNavigationBar;
113 | @property (nonatomic, assign) BOOL showsPageTitleInNavigationBar;
114 |
115 | //Allow for custom activities in the browser by populating this optional array
116 | @property (nonatomic, strong) NSArray *customActivityItems;
117 |
118 | #pragma mark - Public Interface
119 |
120 |
121 | // Load a NSURLURLRequest to web view
122 | // Can be called any time after initialization
123 | - (void)loadRequest:(NSURLRequest *)request;
124 |
125 | // Load a NSURL to web view
126 | // Can be called any time after initialization
127 | - (void)loadURL:(NSURL *)URL;
128 |
129 | // Loads a URL as NSString to web view
130 | // Can be called any time after initialization
131 | - (void)loadURLString:(NSString *)URLString;
132 |
133 |
134 | // Loads an string containing HTML to web view
135 | // Can be called any time after initialization
136 | - (void)loadHTMLString:(NSString *)HTMLString;
137 |
138 | @end
139 |
140 |
--------------------------------------------------------------------------------
/ExampleProject/KINWebBrowserExample.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 0B4A989B6C1762F306885B5D /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D246F90867446D07C788DCE /* libPods.a */; };
11 | 3BBECF2918A1E58D00A2499D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BBECF2818A1E58D00A2499D /* Foundation.framework */; };
12 | 3BBECF2B18A1E58D00A2499D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BBECF2A18A1E58D00A2499D /* CoreGraphics.framework */; };
13 | 3BBECF2D18A1E58D00A2499D /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BBECF2C18A1E58D00A2499D /* UIKit.framework */; };
14 | 3BBECF3318A1E58D00A2499D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3BBECF3118A1E58D00A2499D /* InfoPlist.strings */; };
15 | 3BBECF3518A1E58D00A2499D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BBECF3418A1E58D00A2499D /* main.m */; };
16 | 3BBECF3918A1E58D00A2499D /* KINAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BBECF3818A1E58D00A2499D /* KINAppDelegate.m */; };
17 | 3BBECF3B18A1E58D00A2499D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3BBECF3A18A1E58D00A2499D /* Images.xcassets */; };
18 | 3BBECF4218A1E58D00A2499D /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BBECF4118A1E58D00A2499D /* XCTest.framework */; };
19 | 3BBECF4318A1E58E00A2499D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BBECF2818A1E58D00A2499D /* Foundation.framework */; };
20 | 3BBECF4418A1E58E00A2499D /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BBECF2C18A1E58D00A2499D /* UIKit.framework */; };
21 | 3BBECF4C18A1E58E00A2499D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3BBECF4A18A1E58E00A2499D /* InfoPlist.strings */; };
22 | 3BBECF4E18A1E58E00A2499D /* KINWebBrowserExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BBECF4D18A1E58E00A2499D /* KINWebBrowserExampleTests.m */; };
23 | 3BBECF6518A1EAB100A2499D /* KINWebBrowserExampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BBECF6318A1EAB100A2499D /* KINWebBrowserExampleViewController.m */; };
24 | 3BBECF6618A1EAB100A2499D /* KINWebBrowserExampleViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3BBECF6418A1EAB100A2499D /* KINWebBrowserExampleViewController.xib */; };
25 | /* End PBXBuildFile section */
26 |
27 | /* Begin PBXContainerItemProxy section */
28 | 3BBECF4518A1E58E00A2499D /* PBXContainerItemProxy */ = {
29 | isa = PBXContainerItemProxy;
30 | containerPortal = 3BBECF1D18A1E58D00A2499D /* Project object */;
31 | proxyType = 1;
32 | remoteGlobalIDString = 3BBECF2418A1E58D00A2499D;
33 | remoteInfo = KINWebBrowserExample;
34 | };
35 | /* End PBXContainerItemProxy section */
36 |
37 | /* Begin PBXFileReference section */
38 | 0D66287F09CB3E898333BDB8 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; };
39 | 3B57DAB619E11FAB00C499B5 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
40 | 3BBECF2518A1E58D00A2499D /* KINWebBrowserExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KINWebBrowserExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
41 | 3BBECF2818A1E58D00A2499D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
42 | 3BBECF2A18A1E58D00A2499D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
43 | 3BBECF2C18A1E58D00A2499D /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
44 | 3BBECF3018A1E58D00A2499D /* KINWebBrowserExample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KINWebBrowserExample-Info.plist"; sourceTree = ""; };
45 | 3BBECF3218A1E58D00A2499D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
46 | 3BBECF3418A1E58D00A2499D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
47 | 3BBECF3618A1E58D00A2499D /* KINWebBrowserExample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "KINWebBrowserExample-Prefix.pch"; sourceTree = ""; };
48 | 3BBECF3718A1E58D00A2499D /* KINAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KINAppDelegate.h; sourceTree = ""; };
49 | 3BBECF3818A1E58D00A2499D /* KINAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KINAppDelegate.m; sourceTree = ""; };
50 | 3BBECF3A18A1E58D00A2499D /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
51 | 3BBECF4018A1E58D00A2499D /* KINWebBrowserExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KINWebBrowserExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
52 | 3BBECF4118A1E58D00A2499D /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
53 | 3BBECF4918A1E58E00A2499D /* KINWebBrowserExampleTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KINWebBrowserExampleTests-Info.plist"; sourceTree = ""; };
54 | 3BBECF4B18A1E58E00A2499D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
55 | 3BBECF4D18A1E58E00A2499D /* KINWebBrowserExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KINWebBrowserExampleTests.m; sourceTree = ""; };
56 | 3BBECF6218A1EAB100A2499D /* KINWebBrowserExampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KINWebBrowserExampleViewController.h; sourceTree = ""; };
57 | 3BBECF6318A1EAB100A2499D /* KINWebBrowserExampleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KINWebBrowserExampleViewController.m; sourceTree = ""; };
58 | 3BBECF6418A1EAB100A2499D /* KINWebBrowserExampleViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KINWebBrowserExampleViewController.xib; sourceTree = ""; };
59 | 4D246F90867446D07C788DCE /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
60 | E95061206B0428F84E5EAF94 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; };
61 | /* End PBXFileReference section */
62 |
63 | /* Begin PBXFrameworksBuildPhase section */
64 | 3BBECF2218A1E58D00A2499D /* Frameworks */ = {
65 | isa = PBXFrameworksBuildPhase;
66 | buildActionMask = 2147483647;
67 | files = (
68 | 3BBECF2B18A1E58D00A2499D /* CoreGraphics.framework in Frameworks */,
69 | 3BBECF2D18A1E58D00A2499D /* UIKit.framework in Frameworks */,
70 | 3BBECF2918A1E58D00A2499D /* Foundation.framework in Frameworks */,
71 | 0B4A989B6C1762F306885B5D /* libPods.a in Frameworks */,
72 | );
73 | runOnlyForDeploymentPostprocessing = 0;
74 | };
75 | 3BBECF3D18A1E58D00A2499D /* Frameworks */ = {
76 | isa = PBXFrameworksBuildPhase;
77 | buildActionMask = 2147483647;
78 | files = (
79 | 3BBECF4218A1E58D00A2499D /* XCTest.framework in Frameworks */,
80 | 3BBECF4418A1E58E00A2499D /* UIKit.framework in Frameworks */,
81 | 3BBECF4318A1E58E00A2499D /* Foundation.framework in Frameworks */,
82 | );
83 | runOnlyForDeploymentPostprocessing = 0;
84 | };
85 | /* End PBXFrameworksBuildPhase section */
86 |
87 | /* Begin PBXGroup section */
88 | 3BBECF1C18A1E58D00A2499D = {
89 | isa = PBXGroup;
90 | children = (
91 | 3BBECF2E18A1E58D00A2499D /* KINWebBrowserExample */,
92 | 3BBECF4718A1E58E00A2499D /* KINWebBrowserExampleTests */,
93 | 3BBECF2718A1E58D00A2499D /* Frameworks */,
94 | 3BBECF2618A1E58D00A2499D /* Products */,
95 | F41A3D371A44A50919509CDE /* Pods */,
96 | );
97 | sourceTree = "";
98 | };
99 | 3BBECF2618A1E58D00A2499D /* Products */ = {
100 | isa = PBXGroup;
101 | children = (
102 | 3BBECF2518A1E58D00A2499D /* KINWebBrowserExample.app */,
103 | 3BBECF4018A1E58D00A2499D /* KINWebBrowserExampleTests.xctest */,
104 | );
105 | name = Products;
106 | sourceTree = "";
107 | };
108 | 3BBECF2718A1E58D00A2499D /* Frameworks */ = {
109 | isa = PBXGroup;
110 | children = (
111 | 3B57DAB619E11FAB00C499B5 /* WebKit.framework */,
112 | 3BBECF2818A1E58D00A2499D /* Foundation.framework */,
113 | 3BBECF2A18A1E58D00A2499D /* CoreGraphics.framework */,
114 | 3BBECF2C18A1E58D00A2499D /* UIKit.framework */,
115 | 3BBECF4118A1E58D00A2499D /* XCTest.framework */,
116 | 4D246F90867446D07C788DCE /* libPods.a */,
117 | );
118 | name = Frameworks;
119 | sourceTree = "";
120 | };
121 | 3BBECF2E18A1E58D00A2499D /* KINWebBrowserExample */ = {
122 | isa = PBXGroup;
123 | children = (
124 | 3BBECF3718A1E58D00A2499D /* KINAppDelegate.h */,
125 | 3BBECF3818A1E58D00A2499D /* KINAppDelegate.m */,
126 | 3BBECF6218A1EAB100A2499D /* KINWebBrowserExampleViewController.h */,
127 | 3BBECF6318A1EAB100A2499D /* KINWebBrowserExampleViewController.m */,
128 | 3BBECF6418A1EAB100A2499D /* KINWebBrowserExampleViewController.xib */,
129 | 3BBECF3A18A1E58D00A2499D /* Images.xcassets */,
130 | 3BBECF2F18A1E58D00A2499D /* Supporting Files */,
131 | );
132 | path = KINWebBrowserExample;
133 | sourceTree = "";
134 | };
135 | 3BBECF2F18A1E58D00A2499D /* Supporting Files */ = {
136 | isa = PBXGroup;
137 | children = (
138 | 3BBECF3018A1E58D00A2499D /* KINWebBrowserExample-Info.plist */,
139 | 3BBECF3118A1E58D00A2499D /* InfoPlist.strings */,
140 | 3BBECF3418A1E58D00A2499D /* main.m */,
141 | 3BBECF3618A1E58D00A2499D /* KINWebBrowserExample-Prefix.pch */,
142 | );
143 | name = "Supporting Files";
144 | sourceTree = "";
145 | };
146 | 3BBECF4718A1E58E00A2499D /* KINWebBrowserExampleTests */ = {
147 | isa = PBXGroup;
148 | children = (
149 | 3BBECF4D18A1E58E00A2499D /* KINWebBrowserExampleTests.m */,
150 | 3BBECF4818A1E58E00A2499D /* Supporting Files */,
151 | );
152 | path = KINWebBrowserExampleTests;
153 | sourceTree = "";
154 | };
155 | 3BBECF4818A1E58E00A2499D /* Supporting Files */ = {
156 | isa = PBXGroup;
157 | children = (
158 | 3BBECF4918A1E58E00A2499D /* KINWebBrowserExampleTests-Info.plist */,
159 | 3BBECF4A18A1E58E00A2499D /* InfoPlist.strings */,
160 | );
161 | name = "Supporting Files";
162 | sourceTree = "";
163 | };
164 | F41A3D371A44A50919509CDE /* Pods */ = {
165 | isa = PBXGroup;
166 | children = (
167 | E95061206B0428F84E5EAF94 /* Pods.debug.xcconfig */,
168 | 0D66287F09CB3E898333BDB8 /* Pods.release.xcconfig */,
169 | );
170 | name = Pods;
171 | sourceTree = "";
172 | };
173 | /* End PBXGroup section */
174 |
175 | /* Begin PBXNativeTarget section */
176 | 3BBECF2418A1E58D00A2499D /* KINWebBrowserExample */ = {
177 | isa = PBXNativeTarget;
178 | buildConfigurationList = 3BBECF5118A1E58E00A2499D /* Build configuration list for PBXNativeTarget "KINWebBrowserExample" */;
179 | buildPhases = (
180 | 6F51916B9AD244238CE3E060 /* Check Pods Manifest.lock */,
181 | 3BBECF2118A1E58D00A2499D /* Sources */,
182 | 3BBECF2218A1E58D00A2499D /* Frameworks */,
183 | 3BBECF2318A1E58D00A2499D /* Resources */,
184 | F23BEC6F0D11442D85D78196 /* Copy Pods Resources */,
185 | );
186 | buildRules = (
187 | );
188 | dependencies = (
189 | );
190 | name = KINWebBrowserExample;
191 | productName = KINWebBrowserExample;
192 | productReference = 3BBECF2518A1E58D00A2499D /* KINWebBrowserExample.app */;
193 | productType = "com.apple.product-type.application";
194 | };
195 | 3BBECF3F18A1E58D00A2499D /* KINWebBrowserExampleTests */ = {
196 | isa = PBXNativeTarget;
197 | buildConfigurationList = 3BBECF5418A1E58E00A2499D /* Build configuration list for PBXNativeTarget "KINWebBrowserExampleTests" */;
198 | buildPhases = (
199 | 3BBECF3C18A1E58D00A2499D /* Sources */,
200 | 3BBECF3D18A1E58D00A2499D /* Frameworks */,
201 | 3BBECF3E18A1E58D00A2499D /* Resources */,
202 | );
203 | buildRules = (
204 | );
205 | dependencies = (
206 | 3BBECF4618A1E58E00A2499D /* PBXTargetDependency */,
207 | );
208 | name = KINWebBrowserExampleTests;
209 | productName = KINWebBrowserExampleTests;
210 | productReference = 3BBECF4018A1E58D00A2499D /* KINWebBrowserExampleTests.xctest */;
211 | productType = "com.apple.product-type.bundle.unit-test";
212 | };
213 | /* End PBXNativeTarget section */
214 |
215 | /* Begin PBXProject section */
216 | 3BBECF1D18A1E58D00A2499D /* Project object */ = {
217 | isa = PBXProject;
218 | attributes = {
219 | CLASSPREFIX = KIN;
220 | LastUpgradeCheck = 0600;
221 | ORGANIZATIONNAME = "Kinwa, Inc.";
222 | TargetAttributes = {
223 | 3BBECF3F18A1E58D00A2499D = {
224 | TestTargetID = 3BBECF2418A1E58D00A2499D;
225 | };
226 | };
227 | };
228 | buildConfigurationList = 3BBECF2018A1E58D00A2499D /* Build configuration list for PBXProject "KINWebBrowserExample" */;
229 | compatibilityVersion = "Xcode 3.2";
230 | developmentRegion = English;
231 | hasScannedForEncodings = 0;
232 | knownRegions = (
233 | en,
234 | );
235 | mainGroup = 3BBECF1C18A1E58D00A2499D;
236 | productRefGroup = 3BBECF2618A1E58D00A2499D /* Products */;
237 | projectDirPath = "";
238 | projectRoot = "";
239 | targets = (
240 | 3BBECF2418A1E58D00A2499D /* KINWebBrowserExample */,
241 | 3BBECF3F18A1E58D00A2499D /* KINWebBrowserExampleTests */,
242 | );
243 | };
244 | /* End PBXProject section */
245 |
246 | /* Begin PBXResourcesBuildPhase section */
247 | 3BBECF2318A1E58D00A2499D /* Resources */ = {
248 | isa = PBXResourcesBuildPhase;
249 | buildActionMask = 2147483647;
250 | files = (
251 | 3BBECF6618A1EAB100A2499D /* KINWebBrowserExampleViewController.xib in Resources */,
252 | 3BBECF3318A1E58D00A2499D /* InfoPlist.strings in Resources */,
253 | 3BBECF3B18A1E58D00A2499D /* Images.xcassets in Resources */,
254 | );
255 | runOnlyForDeploymentPostprocessing = 0;
256 | };
257 | 3BBECF3E18A1E58D00A2499D /* Resources */ = {
258 | isa = PBXResourcesBuildPhase;
259 | buildActionMask = 2147483647;
260 | files = (
261 | 3BBECF4C18A1E58E00A2499D /* InfoPlist.strings in Resources */,
262 | );
263 | runOnlyForDeploymentPostprocessing = 0;
264 | };
265 | /* End PBXResourcesBuildPhase section */
266 |
267 | /* Begin PBXShellScriptBuildPhase section */
268 | 6F51916B9AD244238CE3E060 /* Check Pods Manifest.lock */ = {
269 | isa = PBXShellScriptBuildPhase;
270 | buildActionMask = 2147483647;
271 | files = (
272 | );
273 | inputPaths = (
274 | );
275 | name = "Check Pods Manifest.lock";
276 | outputPaths = (
277 | );
278 | runOnlyForDeploymentPostprocessing = 0;
279 | shellPath = /bin/sh;
280 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
281 | showEnvVarsInLog = 0;
282 | };
283 | F23BEC6F0D11442D85D78196 /* Copy Pods Resources */ = {
284 | isa = PBXShellScriptBuildPhase;
285 | buildActionMask = 2147483647;
286 | files = (
287 | );
288 | inputPaths = (
289 | );
290 | name = "Copy Pods Resources";
291 | outputPaths = (
292 | );
293 | runOnlyForDeploymentPostprocessing = 0;
294 | shellPath = /bin/sh;
295 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
296 | showEnvVarsInLog = 0;
297 | };
298 | /* End PBXShellScriptBuildPhase section */
299 |
300 | /* Begin PBXSourcesBuildPhase section */
301 | 3BBECF2118A1E58D00A2499D /* Sources */ = {
302 | isa = PBXSourcesBuildPhase;
303 | buildActionMask = 2147483647;
304 | files = (
305 | 3BBECF3518A1E58D00A2499D /* main.m in Sources */,
306 | 3BBECF6518A1EAB100A2499D /* KINWebBrowserExampleViewController.m in Sources */,
307 | 3BBECF3918A1E58D00A2499D /* KINAppDelegate.m in Sources */,
308 | );
309 | runOnlyForDeploymentPostprocessing = 0;
310 | };
311 | 3BBECF3C18A1E58D00A2499D /* Sources */ = {
312 | isa = PBXSourcesBuildPhase;
313 | buildActionMask = 2147483647;
314 | files = (
315 | 3BBECF4E18A1E58E00A2499D /* KINWebBrowserExampleTests.m in Sources */,
316 | );
317 | runOnlyForDeploymentPostprocessing = 0;
318 | };
319 | /* End PBXSourcesBuildPhase section */
320 |
321 | /* Begin PBXTargetDependency section */
322 | 3BBECF4618A1E58E00A2499D /* PBXTargetDependency */ = {
323 | isa = PBXTargetDependency;
324 | target = 3BBECF2418A1E58D00A2499D /* KINWebBrowserExample */;
325 | targetProxy = 3BBECF4518A1E58E00A2499D /* PBXContainerItemProxy */;
326 | };
327 | /* End PBXTargetDependency section */
328 |
329 | /* Begin PBXVariantGroup section */
330 | 3BBECF3118A1E58D00A2499D /* InfoPlist.strings */ = {
331 | isa = PBXVariantGroup;
332 | children = (
333 | 3BBECF3218A1E58D00A2499D /* en */,
334 | );
335 | name = InfoPlist.strings;
336 | sourceTree = "";
337 | };
338 | 3BBECF4A18A1E58E00A2499D /* InfoPlist.strings */ = {
339 | isa = PBXVariantGroup;
340 | children = (
341 | 3BBECF4B18A1E58E00A2499D /* en */,
342 | );
343 | name = InfoPlist.strings;
344 | sourceTree = "";
345 | };
346 | /* End PBXVariantGroup section */
347 |
348 | /* Begin XCBuildConfiguration section */
349 | 3BBECF4F18A1E58E00A2499D /* Debug */ = {
350 | isa = XCBuildConfiguration;
351 | buildSettings = {
352 | ALWAYS_SEARCH_USER_PATHS = NO;
353 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
354 | CLANG_CXX_LIBRARY = "libc++";
355 | CLANG_ENABLE_MODULES = YES;
356 | CLANG_ENABLE_OBJC_ARC = YES;
357 | CLANG_WARN_BOOL_CONVERSION = YES;
358 | CLANG_WARN_CONSTANT_CONVERSION = YES;
359 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
360 | CLANG_WARN_EMPTY_BODY = YES;
361 | CLANG_WARN_ENUM_CONVERSION = YES;
362 | CLANG_WARN_INT_CONVERSION = YES;
363 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
364 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
365 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
366 | COPY_PHASE_STRIP = NO;
367 | GCC_C_LANGUAGE_STANDARD = gnu99;
368 | GCC_DYNAMIC_NO_PIC = NO;
369 | GCC_OPTIMIZATION_LEVEL = 0;
370 | GCC_PREPROCESSOR_DEFINITIONS = (
371 | "DEBUG=1",
372 | "$(inherited)",
373 | );
374 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
375 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
376 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
377 | GCC_WARN_UNDECLARED_SELECTOR = YES;
378 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
379 | GCC_WARN_UNUSED_FUNCTION = YES;
380 | GCC_WARN_UNUSED_VARIABLE = YES;
381 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
382 | ONLY_ACTIVE_ARCH = YES;
383 | SDKROOT = iphoneos;
384 | TARGETED_DEVICE_FAMILY = "1,2";
385 | };
386 | name = Debug;
387 | };
388 | 3BBECF5018A1E58E00A2499D /* Release */ = {
389 | isa = XCBuildConfiguration;
390 | buildSettings = {
391 | ALWAYS_SEARCH_USER_PATHS = NO;
392 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
393 | CLANG_CXX_LIBRARY = "libc++";
394 | CLANG_ENABLE_MODULES = YES;
395 | CLANG_ENABLE_OBJC_ARC = YES;
396 | CLANG_WARN_BOOL_CONVERSION = YES;
397 | CLANG_WARN_CONSTANT_CONVERSION = YES;
398 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
399 | CLANG_WARN_EMPTY_BODY = YES;
400 | CLANG_WARN_ENUM_CONVERSION = YES;
401 | CLANG_WARN_INT_CONVERSION = YES;
402 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
403 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
404 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
405 | COPY_PHASE_STRIP = YES;
406 | ENABLE_NS_ASSERTIONS = NO;
407 | GCC_C_LANGUAGE_STANDARD = gnu99;
408 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
409 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
410 | GCC_WARN_UNDECLARED_SELECTOR = YES;
411 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
412 | GCC_WARN_UNUSED_FUNCTION = YES;
413 | GCC_WARN_UNUSED_VARIABLE = YES;
414 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
415 | SDKROOT = iphoneos;
416 | TARGETED_DEVICE_FAMILY = "1,2";
417 | VALIDATE_PRODUCT = YES;
418 | };
419 | name = Release;
420 | };
421 | 3BBECF5218A1E58E00A2499D /* Debug */ = {
422 | isa = XCBuildConfiguration;
423 | baseConfigurationReference = E95061206B0428F84E5EAF94 /* Pods.debug.xcconfig */;
424 | buildSettings = {
425 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
426 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
427 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
428 | GCC_PREFIX_HEADER = "KINWebBrowserExample/KINWebBrowserExample-Prefix.pch";
429 | INFOPLIST_FILE = "KINWebBrowserExample/KINWebBrowserExample-Info.plist";
430 | PRODUCT_NAME = "$(TARGET_NAME)";
431 | WRAPPER_EXTENSION = app;
432 | };
433 | name = Debug;
434 | };
435 | 3BBECF5318A1E58E00A2499D /* Release */ = {
436 | isa = XCBuildConfiguration;
437 | baseConfigurationReference = 0D66287F09CB3E898333BDB8 /* Pods.release.xcconfig */;
438 | buildSettings = {
439 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
440 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
441 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
442 | GCC_PREFIX_HEADER = "KINWebBrowserExample/KINWebBrowserExample-Prefix.pch";
443 | INFOPLIST_FILE = "KINWebBrowserExample/KINWebBrowserExample-Info.plist";
444 | PRODUCT_NAME = "$(TARGET_NAME)";
445 | WRAPPER_EXTENSION = app;
446 | };
447 | name = Release;
448 | };
449 | 3BBECF5518A1E58E00A2499D /* Debug */ = {
450 | isa = XCBuildConfiguration;
451 | buildSettings = {
452 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/KINWebBrowserExample.app/KINWebBrowserExample";
453 | FRAMEWORK_SEARCH_PATHS = (
454 | "$(SDKROOT)/Developer/Library/Frameworks",
455 | "$(inherited)",
456 | "$(DEVELOPER_FRAMEWORKS_DIR)",
457 | );
458 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
459 | GCC_PREFIX_HEADER = "KINWebBrowserExample/KINWebBrowserExample-Prefix.pch";
460 | GCC_PREPROCESSOR_DEFINITIONS = (
461 | "DEBUG=1",
462 | "$(inherited)",
463 | );
464 | INFOPLIST_FILE = "KINWebBrowserExampleTests/KINWebBrowserExampleTests-Info.plist";
465 | PRODUCT_NAME = "$(TARGET_NAME)";
466 | TEST_HOST = "$(BUNDLE_LOADER)";
467 | WRAPPER_EXTENSION = xctest;
468 | };
469 | name = Debug;
470 | };
471 | 3BBECF5618A1E58E00A2499D /* Release */ = {
472 | isa = XCBuildConfiguration;
473 | buildSettings = {
474 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/KINWebBrowserExample.app/KINWebBrowserExample";
475 | FRAMEWORK_SEARCH_PATHS = (
476 | "$(SDKROOT)/Developer/Library/Frameworks",
477 | "$(inherited)",
478 | "$(DEVELOPER_FRAMEWORKS_DIR)",
479 | );
480 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
481 | GCC_PREFIX_HEADER = "KINWebBrowserExample/KINWebBrowserExample-Prefix.pch";
482 | INFOPLIST_FILE = "KINWebBrowserExampleTests/KINWebBrowserExampleTests-Info.plist";
483 | PRODUCT_NAME = "$(TARGET_NAME)";
484 | TEST_HOST = "$(BUNDLE_LOADER)";
485 | WRAPPER_EXTENSION = xctest;
486 | };
487 | name = Release;
488 | };
489 | /* End XCBuildConfiguration section */
490 |
491 | /* Begin XCConfigurationList section */
492 | 3BBECF2018A1E58D00A2499D /* Build configuration list for PBXProject "KINWebBrowserExample" */ = {
493 | isa = XCConfigurationList;
494 | buildConfigurations = (
495 | 3BBECF4F18A1E58E00A2499D /* Debug */,
496 | 3BBECF5018A1E58E00A2499D /* Release */,
497 | );
498 | defaultConfigurationIsVisible = 0;
499 | defaultConfigurationName = Release;
500 | };
501 | 3BBECF5118A1E58E00A2499D /* Build configuration list for PBXNativeTarget "KINWebBrowserExample" */ = {
502 | isa = XCConfigurationList;
503 | buildConfigurations = (
504 | 3BBECF5218A1E58E00A2499D /* Debug */,
505 | 3BBECF5318A1E58E00A2499D /* Release */,
506 | );
507 | defaultConfigurationIsVisible = 0;
508 | defaultConfigurationName = Release;
509 | };
510 | 3BBECF5418A1E58E00A2499D /* Build configuration list for PBXNativeTarget "KINWebBrowserExampleTests" */ = {
511 | isa = XCConfigurationList;
512 | buildConfigurations = (
513 | 3BBECF5518A1E58E00A2499D /* Debug */,
514 | 3BBECF5618A1E58E00A2499D /* Release */,
515 | );
516 | defaultConfigurationIsVisible = 0;
517 | defaultConfigurationName = Release;
518 | };
519 | /* End XCConfigurationList section */
520 | };
521 | rootObject = 3BBECF1D18A1E58D00A2499D /* Project object */;
522 | }
523 |
--------------------------------------------------------------------------------
/KINWebBrowser/KINWebBrowserViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // KINWebBrowserViewController.m
3 | //
4 | // KINWebBrowser
5 | //
6 | // Created by David F. Muir V
7 | // dfmuir@gmail.com
8 | // Co-Founder & Engineer at Kinwa, Inc.
9 | // http://www.kinwa.co
10 | //
11 | // The MIT License (MIT)
12 | //
13 | // Copyright (c) 2014 David Muir
14 | //
15 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
16 | // this software and associated documentation files (the "Software"), to deal in
17 | // the Software without restriction, including without limitation the rights to
18 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
19 | // the Software, and to permit persons to whom the Software is furnished to do so,
20 | // subject to the following conditions:
21 | //
22 | // The above copyright notice and this permission notice shall be included in all
23 | // copies or substantial portions of the Software.
24 | //
25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
27 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
28 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
29 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 | //
32 |
33 | #import "KINWebBrowserViewController.h"
34 |
35 | #import "TUSafariActivity.h"
36 | #import "ARChromeActivity.h"
37 |
38 | static void *KINWebBrowserContext = &KINWebBrowserContext;
39 |
40 | @interface KINWebBrowserViewController ()
41 |
42 | @property (nonatomic, assign) BOOL previousNavigationControllerToolbarHidden, previousNavigationControllerNavigationBarHidden;
43 | @property (nonatomic, strong) UIBarButtonItem *backButton, *forwardButton, *refreshButton, *stopButton, *fixedSeparator, *flexibleSeparator;
44 | @property (nonatomic, strong) NSTimer *fakeProgressTimer;
45 | @property (nonatomic, strong) UIPopoverController *actionPopoverController;
46 | @property (nonatomic, assign) BOOL uiWebViewIsLoading;
47 | @property (nonatomic, strong) NSURL *uiWebViewCurrentURL;
48 | @property (nonatomic, strong) NSURL *URLToLaunchWithPermission;
49 | @property (nonatomic, strong) UIAlertView *externalAppPermissionAlertView;
50 |
51 | @end
52 |
53 | @implementation KINWebBrowserViewController
54 |
55 | #pragma mark - Static Initializers
56 |
57 | + (KINWebBrowserViewController *)webBrowser {
58 | KINWebBrowserViewController *webBrowserViewController = [KINWebBrowserViewController webBrowserWithConfiguration:nil];
59 | return webBrowserViewController;
60 | }
61 |
62 | + (KINWebBrowserViewController *)webBrowserWithConfiguration:(WKWebViewConfiguration *)configuration {
63 | KINWebBrowserViewController *webBrowserViewController = [[self alloc] initWithConfiguration:configuration];
64 | return webBrowserViewController;
65 | }
66 |
67 | + (UINavigationController *)navigationControllerWithWebBrowser {
68 | KINWebBrowserViewController *webBrowserViewController = [[self alloc] initWithConfiguration:nil];
69 | return [KINWebBrowserViewController navigationControllerWithBrowser:webBrowserViewController];
70 | }
71 |
72 | + (UINavigationController *)navigationControllerWithWebBrowserWithConfiguration:(WKWebViewConfiguration *)configuration {
73 | KINWebBrowserViewController *webBrowserViewController = [[self alloc] initWithConfiguration:configuration];
74 | return [KINWebBrowserViewController navigationControllerWithBrowser:webBrowserViewController];
75 | }
76 |
77 | + (UINavigationController *)navigationControllerWithBrowser:(KINWebBrowserViewController *)webBrowser {
78 | UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:webBrowser action:@selector(doneButtonPressed:)];
79 | [webBrowser.navigationItem setRightBarButtonItem:doneButton];
80 |
81 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:webBrowser];
82 | return navigationController;
83 | }
84 |
85 | #pragma mark - Initializers
86 |
87 | - (id)init {
88 | return [self initWithConfiguration:nil];
89 | }
90 |
91 | - (id)initWithConfiguration:(WKWebViewConfiguration *)configuration {
92 | self = [super init];
93 | if(self) {
94 | if([WKWebView class]) {
95 | if(configuration) {
96 | self.wkWebView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
97 | }
98 | else {
99 | self.wkWebView = [[WKWebView alloc] init];
100 | }
101 | }
102 | else {
103 | self.uiWebView = [[UIWebView alloc] init];
104 | }
105 |
106 | self.actionButtonHidden = NO;
107 | self.showsURLInNavigationBar = NO;
108 | self.showsPageTitleInNavigationBar = YES;
109 |
110 | self.externalAppPermissionAlertView = [[UIAlertView alloc] initWithTitle:@"Leave this app?" message:@"This web page is trying to open an outside app. Are you sure you want to open it?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Open App", nil];
111 |
112 | }
113 | return self;
114 | }
115 |
116 | #pragma mark - View Lifecycle
117 |
118 | - (void)viewDidLoad {
119 | [super viewDidLoad];
120 |
121 | self.previousNavigationControllerToolbarHidden = self.navigationController.toolbarHidden;
122 | self.previousNavigationControllerNavigationBarHidden = self.navigationController.navigationBarHidden;
123 |
124 | if(self.wkWebView) {
125 | [self.wkWebView setFrame:self.view.bounds];
126 | [self.wkWebView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
127 | [self.wkWebView setNavigationDelegate:self];
128 | [self.wkWebView setUIDelegate:self];
129 | [self.wkWebView setMultipleTouchEnabled:YES];
130 | [self.wkWebView setAutoresizesSubviews:YES];
131 | [self.wkWebView.scrollView setAlwaysBounceVertical:YES];
132 | [self.view addSubview:self.wkWebView];
133 |
134 | [self.wkWebView addObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress)) options:0 context:KINWebBrowserContext];
135 | }
136 | else if(self.uiWebView) {
137 | [self.uiWebView setFrame:self.view.bounds];
138 | [self.uiWebView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
139 | [self.uiWebView setDelegate:self];
140 | [self.uiWebView setMultipleTouchEnabled:YES];
141 | [self.uiWebView setAutoresizesSubviews:YES];
142 | [self.uiWebView setScalesPageToFit:YES];
143 | [self.uiWebView.scrollView setAlwaysBounceVertical:YES];
144 | [self.view addSubview:self.uiWebView];
145 | }
146 |
147 |
148 | self.progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
149 | [self.progressView setTrackTintColor:[UIColor colorWithWhite:1.0f alpha:0.0f]];
150 | [self.progressView setFrame:CGRectMake(0, self.navigationController.navigationBar.frame.size.height-self.progressView.frame.size.height, self.view.frame.size.width, self.progressView.frame.size.height)];
151 | [self.progressView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin];
152 | }
153 |
154 | - (void)viewWillAppear:(BOOL)animated {
155 | [super viewWillAppear:animated];
156 |
157 | [self.navigationController setNavigationBarHidden:NO animated:YES];
158 | [self.navigationController setToolbarHidden:NO animated:YES];
159 |
160 | [self.navigationController.navigationBar addSubview:self.progressView];
161 |
162 | [self updateToolbarState];
163 | }
164 |
165 | - (void)viewWillDisappear:(BOOL)animated {
166 | [super viewWillDisappear:animated];
167 |
168 | [self.navigationController setNavigationBarHidden:self.previousNavigationControllerNavigationBarHidden animated:animated];
169 |
170 | [self.navigationController setToolbarHidden:self.previousNavigationControllerToolbarHidden animated:animated];
171 |
172 | [self.uiWebView setDelegate:nil];
173 | [self.progressView removeFromSuperview];
174 | }
175 |
176 | #pragma mark - Public Interface
177 |
178 | - (void)loadRequest:(NSURLRequest *)request {
179 | if(self.wkWebView) {
180 | [self.wkWebView loadRequest:request];
181 | }
182 | else if(self.uiWebView) {
183 | [self.uiWebView loadRequest:request];
184 | }
185 | }
186 |
187 | - (void)loadURL:(NSURL *)URL {
188 | [self loadRequest:[NSURLRequest requestWithURL:URL]];
189 | }
190 |
191 | - (void)loadURLString:(NSString *)URLString {
192 | NSURL *URL = [NSURL URLWithString:URLString];
193 | [self loadURL:URL];
194 | }
195 |
196 | - (void)loadHTMLString:(NSString *)HTMLString {
197 | if(self.wkWebView) {
198 | [self.wkWebView loadHTMLString:HTMLString baseURL:nil];
199 | }
200 | else if(self.uiWebView) {
201 | [self.uiWebView loadHTMLString:HTMLString baseURL:nil];
202 | }
203 | }
204 |
205 | - (void)setTintColor:(UIColor *)tintColor {
206 | _tintColor = tintColor;
207 | [self.progressView setTintColor:tintColor];
208 | [self.navigationController.navigationBar setTintColor:tintColor];
209 | [self.navigationController.toolbar setTintColor:tintColor];
210 | }
211 |
212 | - (void)setBarTintColor:(UIColor *)barTintColor {
213 | _barTintColor = barTintColor;
214 | [self.navigationController.navigationBar setBarTintColor:barTintColor];
215 | [self.navigationController.toolbar setBarTintColor:barTintColor];
216 | }
217 |
218 | - (void)setActionButtonHidden:(BOOL)actionButtonHidden {
219 | _actionButtonHidden = actionButtonHidden;
220 | [self updateToolbarState];
221 | }
222 |
223 |
224 | #pragma mark - UIWebViewDelegate
225 |
226 | - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
227 | if(webView == self.uiWebView) {
228 |
229 | if(![self externalAppRequiredToOpenURL:request.URL]) {
230 | self.uiWebViewCurrentURL = request.URL;
231 | self.uiWebViewIsLoading = YES;
232 | [self updateToolbarState];
233 |
234 | [self fakeProgressViewStartLoading];
235 |
236 | if([self.delegate respondsToSelector:@selector(webBrowser:didStartLoadingURL:)]) {
237 | [self.delegate webBrowser:self didStartLoadingURL:request.URL];
238 | }
239 | return YES;
240 | }
241 | else {
242 | [self launchExternalAppWithURL:request.URL];
243 | return NO;
244 | }
245 | }
246 | return NO;
247 | }
248 |
249 | - (void)webViewDidFinishLoad:(UIWebView *)webView {
250 | if(webView == self.uiWebView) {
251 | if(!self.uiWebView.isLoading) {
252 | self.uiWebViewIsLoading = NO;
253 | [self updateToolbarState];
254 |
255 | [self fakeProgressBarStopLoading];
256 | }
257 |
258 | if([self.delegate respondsToSelector:@selector(webBrowser:didFinishLoadingURL:)]) {
259 | [self.delegate webBrowser:self didFinishLoadingURL:self.uiWebView.request.URL];
260 | }
261 | }
262 | }
263 |
264 | - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
265 | if(webView == self.uiWebView) {
266 | if(!self.uiWebView.isLoading) {
267 | self.uiWebViewIsLoading = NO;
268 | [self updateToolbarState];
269 |
270 | [self fakeProgressBarStopLoading];
271 | }
272 | if([self.delegate respondsToSelector:@selector(webBrowser:didFailToLoadURL:error:)]) {
273 | [self.delegate webBrowser:self didFailToLoadURL:self.uiWebView.request.URL error:error];
274 | }
275 | }
276 | }
277 |
278 | #pragma mark - WKNavigationDelegate
279 |
280 | - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
281 | if(webView == self.wkWebView) {
282 | [self updateToolbarState];
283 | if([self.delegate respondsToSelector:@selector(webBrowser:didStartLoadingURL:)]) {
284 | [self.delegate webBrowser:self didStartLoadingURL:self.wkWebView.URL];
285 | }
286 | }
287 | }
288 |
289 | - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
290 | if(webView == self.wkWebView) {
291 | [self updateToolbarState];
292 | if([self.delegate respondsToSelector:@selector(webBrowser:didFinishLoadingURL:)]) {
293 | [self.delegate webBrowser:self didFinishLoadingURL:self.wkWebView.URL];
294 | }
295 | }
296 | }
297 |
298 | - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation
299 | withError:(NSError *)error {
300 | if(webView == self.wkWebView) {
301 | [self updateToolbarState];
302 | if([self.delegate respondsToSelector:@selector(webBrowser:didFailToLoadURL:error:)]) {
303 | [self.delegate webBrowser:self didFailToLoadURL:self.wkWebView.URL error:error];
304 | }
305 | }
306 | }
307 |
308 | - (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation
309 | withError:(NSError *)error {
310 | if(webView == self.wkWebView) {
311 | [self updateToolbarState];
312 | if([self.delegate respondsToSelector:@selector(webBrowser:didFailToLoadURL:error:)]) {
313 | [self.delegate webBrowser:self didFailToLoadURL:self.wkWebView.URL error:error];
314 | }
315 | }
316 | }
317 |
318 | - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
319 | if(webView == self.wkWebView) {
320 |
321 | NSURL *URL = navigationAction.request.URL;
322 | if(![self externalAppRequiredToOpenURL:URL]) {
323 | if(!navigationAction.targetFrame) {
324 | [self loadURL:URL];
325 | decisionHandler(WKNavigationActionPolicyCancel);
326 | return;
327 | }
328 | }
329 | else if([[UIApplication sharedApplication] canOpenURL:URL]) {
330 | [self launchExternalAppWithURL:URL];
331 | decisionHandler(WKNavigationActionPolicyCancel);
332 | return;
333 | }
334 | }
335 | decisionHandler(WKNavigationActionPolicyAllow);
336 | }
337 |
338 | #pragma mark - WKUIDelegate
339 |
340 | - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
341 | if (!navigationAction.targetFrame.isMainFrame) {
342 | [webView loadRequest:navigationAction.request];
343 | }
344 | return nil;
345 | }
346 |
347 | #pragma mark - Toolbar State
348 |
349 | - (void)updateToolbarState {
350 |
351 | BOOL canGoBack = self.wkWebView.canGoBack || self.uiWebView.canGoBack;
352 | BOOL canGoForward = self.wkWebView.canGoForward || self.uiWebView.canGoForward;
353 |
354 | [self.backButton setEnabled:canGoBack];
355 | [self.forwardButton setEnabled:canGoForward];
356 |
357 | if(!self.backButton) {
358 | [self setupToolbarItems];
359 | }
360 |
361 | NSArray *barButtonItems;
362 | if(self.wkWebView.loading || self.uiWebViewIsLoading) {
363 | barButtonItems = @[self.backButton, self.fixedSeparator, self.forwardButton, self.fixedSeparator, self.stopButton, self.flexibleSeparator];
364 |
365 | if(self.showsURLInNavigationBar) {
366 | NSString *URLString;
367 | if(self.wkWebView) {
368 | URLString = [self.wkWebView.URL absoluteString];
369 | }
370 | else if(self.uiWebView) {
371 | URLString = [self.uiWebViewCurrentURL absoluteString];
372 | }
373 |
374 | URLString = [URLString stringByReplacingOccurrencesOfString:@"http://" withString:@""];
375 | URLString = [URLString stringByReplacingOccurrencesOfString:@"https://" withString:@""];
376 | URLString = [URLString substringToIndex:[URLString length]-1];
377 | self.navigationItem.title = URLString;
378 | }
379 | }
380 | else {
381 | barButtonItems = @[self.backButton, self.fixedSeparator, self.forwardButton, self.fixedSeparator, self.refreshButton, self.flexibleSeparator];
382 |
383 | if(self.showsPageTitleInNavigationBar) {
384 | if(self.wkWebView) {
385 | self.navigationItem.title = self.wkWebView.title;
386 | }
387 | else if(self.uiWebView) {
388 | self.navigationItem.title = [self.uiWebView stringByEvaluatingJavaScriptFromString:@"document.title"];
389 | }
390 | }
391 | }
392 |
393 | if(!self.actionButtonHidden) {
394 | NSMutableArray *mutableBarButtonItems = [NSMutableArray arrayWithArray:barButtonItems];
395 | [mutableBarButtonItems addObject:self.actionButton];
396 | barButtonItems = [NSArray arrayWithArray:mutableBarButtonItems];
397 | }
398 |
399 | [self setToolbarItems:barButtonItems animated:YES];
400 |
401 | self.tintColor = self.tintColor;
402 | self.barTintColor = self.barTintColor;
403 |
404 |
405 | }
406 |
407 | - (void)setupToolbarItems {
408 | NSBundle *bundle = [NSBundle bundleForClass:[KINWebBrowserViewController class]];
409 |
410 | self.refreshButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshButtonPressed:)];
411 | self.stopButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop target:self action:@selector(stopButtonPressed:)];
412 |
413 | UIImage *backbuttonImage = [UIImage imageWithContentsOfFile: [bundle pathForResource:@"backbutton" ofType:@"png"]];
414 | self.backButton = [[UIBarButtonItem alloc] initWithImage:backbuttonImage style:UIBarButtonItemStylePlain target:self action:@selector(backButtonPressed:)];
415 |
416 | UIImage *forwardbuttonImage = [UIImage imageWithContentsOfFile: [bundle pathForResource:@"forwardbutton" ofType:@"png"]];
417 | self.forwardButton = [[UIBarButtonItem alloc] initWithImage:forwardbuttonImage style:UIBarButtonItemStylePlain target:self action:@selector(forwardButtonPressed:)];
418 | self.actionButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(actionButtonPressed:)];
419 | self.fixedSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
420 | self.fixedSeparator.width = 50.0f;
421 | self.flexibleSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
422 | }
423 |
424 | #pragma mark - Done Button Action
425 |
426 | - (void)doneButtonPressed:(id)sender {
427 | [self dismissAnimated:YES];
428 | }
429 |
430 | #pragma mark - UIBarButtonItem Target Action Methods
431 |
432 | - (void)backButtonPressed:(id)sender {
433 |
434 | if(self.wkWebView) {
435 | [self.wkWebView goBack];
436 | }
437 | else if(self.uiWebView) {
438 | [self.uiWebView goBack];
439 | }
440 | [self updateToolbarState];
441 | }
442 |
443 | - (void)forwardButtonPressed:(id)sender {
444 | if(self.wkWebView) {
445 | [self.wkWebView goForward];
446 | }
447 | else if(self.uiWebView) {
448 | [self.uiWebView goForward];
449 | }
450 | [self updateToolbarState];
451 | }
452 |
453 | - (void)refreshButtonPressed:(id)sender {
454 | if(self.wkWebView) {
455 | [self.wkWebView stopLoading];
456 | [self.wkWebView reload];
457 | }
458 | else if(self.uiWebView) {
459 | [self.uiWebView stopLoading];
460 | [self.uiWebView reload];
461 | }
462 | }
463 |
464 | - (void)stopButtonPressed:(id)sender {
465 | if(self.wkWebView) {
466 | [self.wkWebView stopLoading];
467 | }
468 | else if(self.uiWebView) {
469 | [self.uiWebView stopLoading];
470 | }
471 | }
472 |
473 | - (void)actionButtonPressed:(id)sender {
474 | NSURL *URLForActivityItem;
475 | NSString *URLTitle;
476 | if(self.wkWebView) {
477 | URLForActivityItem = self.wkWebView.URL;
478 | URLTitle = self.wkWebView.title;
479 | }
480 | else if(self.uiWebView) {
481 | URLForActivityItem = self.uiWebView.request.URL;
482 | URLTitle = [self.uiWebView stringByEvaluatingJavaScriptFromString:@"document.title"];
483 | }
484 | if (URLForActivityItem) {
485 | dispatch_async(dispatch_get_main_queue(), ^{
486 | TUSafariActivity *safariActivity = [[TUSafariActivity alloc] init];
487 | ARChromeActivity *chromeActivity = [[ARChromeActivity alloc] init];
488 |
489 | NSMutableArray *activities = [[NSMutableArray alloc] init];
490 | [activities addObject:safariActivity];
491 | [activities addObject:chromeActivity];
492 | if(self.customActivityItems != nil) {
493 | [activities addObjectsFromArray:self.customActivityItems];
494 | }
495 |
496 | UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:@[URLForActivityItem] applicationActivities:activities];
497 |
498 | if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
499 | if(self.actionPopoverController) {
500 | [self.actionPopoverController dismissPopoverAnimated:YES];
501 | }
502 | self.actionPopoverController = [[UIPopoverController alloc] initWithContentViewController:controller];
503 | [self.actionPopoverController presentPopoverFromBarButtonItem:self.actionButton permittedArrowDirections: UIPopoverArrowDirectionAny animated:YES];
504 | }
505 | else {
506 | [self presentViewController:controller animated:YES completion:NULL];
507 | }
508 | });
509 | }
510 | }
511 |
512 |
513 | #pragma mark - Estimated Progress KVO (WKWebView)
514 |
515 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
516 | if ([keyPath isEqualToString:NSStringFromSelector(@selector(estimatedProgress))] && object == self.wkWebView) {
517 | [self.progressView setAlpha:1.0f];
518 | BOOL animated = self.wkWebView.estimatedProgress > self.progressView.progress;
519 | [self.progressView setProgress:self.wkWebView.estimatedProgress animated:animated];
520 |
521 | // Once complete, fade out UIProgressView
522 | if(self.wkWebView.estimatedProgress >= 1.0f) {
523 | [UIView animateWithDuration:0.3f delay:0.3f options:UIViewAnimationOptionCurveEaseOut animations:^{
524 | [self.progressView setAlpha:0.0f];
525 | } completion:^(BOOL finished) {
526 | [self.progressView setProgress:0.0f animated:NO];
527 | }];
528 | }
529 | }
530 | else {
531 | [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
532 | }
533 | }
534 |
535 |
536 | #pragma mark - Fake Progress Bar Control (UIWebView)
537 |
538 | - (void)fakeProgressViewStartLoading {
539 | [self.progressView setProgress:0.0f animated:NO];
540 | [self.progressView setAlpha:1.0f];
541 |
542 | if(!self.fakeProgressTimer) {
543 | self.fakeProgressTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f/60.0f target:self selector:@selector(fakeProgressTimerDidFire:) userInfo:nil repeats:YES];
544 | }
545 | }
546 |
547 | - (void)fakeProgressBarStopLoading {
548 | if(self.fakeProgressTimer) {
549 | [self.fakeProgressTimer invalidate];
550 | }
551 |
552 | if(self.progressView) {
553 | [self.progressView setProgress:1.0f animated:YES];
554 | [UIView animateWithDuration:0.3f delay:0.3f options:UIViewAnimationOptionCurveEaseOut animations:^{
555 | [self.progressView setAlpha:0.0f];
556 | } completion:^(BOOL finished) {
557 | [self.progressView setProgress:0.0f animated:NO];
558 | }];
559 | }
560 | }
561 |
562 | - (void)fakeProgressTimerDidFire:(id)sender {
563 | CGFloat increment = 0.005/(self.progressView.progress + 0.2);
564 | if([self.uiWebView isLoading]) {
565 | CGFloat progress = (self.progressView.progress < 0.75f) ? self.progressView.progress + increment : self.progressView.progress + 0.0005;
566 | if(self.progressView.progress < 0.95) {
567 | [self.progressView setProgress:progress animated:YES];
568 | }
569 | }
570 | }
571 |
572 | #pragma mark - External App Support
573 |
574 | - (BOOL)externalAppRequiredToOpenURL:(NSURL *)URL {
575 | NSSet *validSchemes = [NSSet setWithArray:@[@"http", @"https"]];
576 | return ![validSchemes containsObject:URL.scheme];
577 | }
578 |
579 | - (void)launchExternalAppWithURL:(NSURL *)URL {
580 | self.URLToLaunchWithPermission = URL;
581 | if (![self.externalAppPermissionAlertView isVisible]) {
582 | [self.externalAppPermissionAlertView show];
583 | }
584 |
585 | }
586 |
587 | #pragma mark - UIAlertViewDelegate
588 |
589 | - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
590 | if(alertView == self.externalAppPermissionAlertView) {
591 | if(buttonIndex != alertView.cancelButtonIndex) {
592 | [[UIApplication sharedApplication] openURL:self.URLToLaunchWithPermission];
593 | }
594 | self.URLToLaunchWithPermission = nil;
595 | }
596 | }
597 |
598 | #pragma mark - Dismiss
599 |
600 | - (void)dismissAnimated:(BOOL)animated {
601 | if([self.delegate respondsToSelector:@selector(webBrowserViewControllerWillDismiss:)]) {
602 | [self.delegate webBrowserViewControllerWillDismiss:self];
603 | }
604 | [self.navigationController dismissViewControllerAnimated:animated completion:nil];
605 | }
606 |
607 | #pragma mark - Interface Orientation
608 |
609 | - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
610 | return UIInterfaceOrientationMaskAllButUpsideDown;
611 | }
612 |
613 | - (BOOL)shouldAutorotate {
614 | return YES;
615 | }
616 |
617 | #pragma mark - Dealloc
618 |
619 | - (void)dealloc {
620 | [self.uiWebView setDelegate:nil];
621 |
622 | [self.wkWebView setNavigationDelegate:nil];
623 | [self.wkWebView setUIDelegate:nil];
624 | if ([self isViewLoaded]) {
625 | [self.wkWebView removeObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress))];
626 | }
627 | }
628 |
629 |
630 | @end
631 |
632 | @implementation UINavigationController(KINWebBrowser)
633 |
634 | - (KINWebBrowserViewController *)rootWebBrowser {
635 | UIViewController *rootViewController = [self.viewControllers objectAtIndex:0];
636 | return (KINWebBrowserViewController *)rootViewController;
637 | }
638 |
639 | @end
640 |
--------------------------------------------------------------------------------