Skip to content

Commit acb00a3

Browse files
committed
working on webview
1 parent 8e2f396 commit acb00a3

File tree

4 files changed

+190
-4
lines changed

4 files changed

+190
-4
lines changed

ios-pwa-wrapper/AppDelegate.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
1717

1818
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
1919
// Override point for customization after application launch.
20+
21+
// Change Navigation style
22+
UINavigationBar.appearance().barTintColor = UIColor.green
23+
UINavigationBar.appearance().titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.orange]
24+
UIBarButtonItem.appearance().tintColor = UIColor.white
25+
2026
return true
2127
}
2228

ios-pwa-wrapper/Assets.xcassets/AppIcon.appiconset/Contents.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@
8484
"idiom" : "ipad",
8585
"size" : "83.5x83.5",
8686
"scale" : "2x"
87+
},
88+
{
89+
"idiom" : "ios-marketing",
90+
"size" : "1024x1024",
91+
"scale" : "1x"
8792
}
8893
],
8994
"info" : {
Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,70 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" systemVersion="17A277" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13196" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ON9-GN-Pta">
3+
<device id="retina4_7" orientation="portrait">
4+
<adaptation id="fullscreen"/>
5+
</device>
36
<dependencies>
4-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
7+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13174"/>
58
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
69
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
710
</dependencies>
811
<scenes>
9-
<!--View Controller-->
12+
<!--PWA Wrapper-->
1013
<scene sceneID="tne-QT-ifu">
1114
<objects>
12-
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
15+
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="ios_pwa_wrapper" customModuleProvider="target" sceneMemberID="viewController">
1316
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
1417
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
1518
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
19+
<subviews>
20+
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HnO-cS-a4I">
21+
<rect key="frame" x="0.0" y="116" width="375" height="551"/>
22+
<autoresizingMask key="autoresizingMask"/>
23+
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
24+
</view>
25+
</subviews>
1626
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
1727
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
1828
</view>
29+
<navigationItem key="navigationItem" title="PWA Wrapper" id="COK-wh-4k6">
30+
<barButtonItem key="leftBarButtonItem" title="Back" id="mlw-cf-kRg">
31+
<connections>
32+
<action selector="onLeftButtonClick:" destination="BYZ-38-t0r" id="D2i-HL-t5s"/>
33+
</connections>
34+
</barButtonItem>
35+
<barButtonItem key="rightBarButtonItem" title="Menu" id="DBy-OS-v6d">
36+
<connections>
37+
<action selector="onRightButtonClick:" destination="BYZ-38-t0r" id="ALm-6g-KOB"/>
38+
</connections>
39+
</barButtonItem>
40+
</navigationItem>
41+
<connections>
42+
<outlet property="leftButton" destination="mlw-cf-kRg" id="5PJ-wX-nGG"/>
43+
<outlet property="rightButton" destination="DBy-OS-v6d" id="A1c-Ll-cgP"/>
44+
<outlet property="webViewContainer" destination="HnO-cS-a4I" id="5NC-tb-0Ov"/>
45+
</connections>
1946
</viewController>
2047
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
2148
</objects>
49+
<point key="canvasLocation" x="1047" y="476"/>
50+
</scene>
51+
<!--Navigation Controller-->
52+
<scene sceneID="1sK-l5-PHi">
53+
<objects>
54+
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="ON9-GN-Pta" sceneMemberID="viewController">
55+
<toolbarItems/>
56+
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="uik-Iv-Zgf">
57+
<rect key="frame" x="0.0" y="20" width="375" height="96"/>
58+
<autoresizingMask key="autoresizingMask"/>
59+
</navigationBar>
60+
<nil name="viewControllers"/>
61+
<connections>
62+
<segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="EHQ-9R-Its"/>
63+
</connections>
64+
</navigationController>
65+
<placeholder placeholderIdentifier="IBFirstResponder" id="Ej4-Id-CRP" userLabel="First Responder" sceneMemberID="firstResponder"/>
66+
</objects>
67+
<point key="canvasLocation" x="113.59999999999999" y="476.76161919040482"/>
2268
</scene>
2369
</scenes>
2470
</document>

ios-pwa-wrapper/ViewController.swift

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,148 @@
77
//
88

99
import UIKit
10+
import WebKit
1011

1112
class ViewController: UIViewController {
13+
14+
// MARK: Outlets
15+
@IBOutlet weak var leftButton: UIBarButtonItem!
16+
@IBOutlet weak var rightButton: UIBarButtonItem!
17+
@IBOutlet weak var webViewContainer: UIView!
18+
// MARK: Globals
19+
var webView: WKWebView!
20+
var progressBar : UIProgressView!
21+
let appUrl = URL(string: "https://www.duckduckgo.com/")
22+
let allowedOrigin = "duckduckgo.com"
1223

1324
override func viewDidLoad() {
1425
super.viewDidLoad()
1526
// Do any additional setup after loading the view, typically from a nib.
27+
setupApp()
1628
}
1729

1830
override func didReceiveMemoryWarning() {
1931
super.didReceiveMemoryWarning()
2032
// Dispose of any resources that can be recreated.
2133
}
34+
35+
// UI Actions
36+
@IBAction func onLeftButtonClick(_ sender: Any) {
37+
if (webView.canGoBack) {
38+
webView.goBack()
39+
}
40+
}
41+
@IBAction func onRightButtonClick(_ sender: Any) {
42+
webView.evaluateJavaScript("alert('boom')", completionHandler: nil)
43+
}
44+
45+
// Observers for updating UI
46+
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
47+
if (keyPath == #keyPath(WKWebView.isLoading)) {
48+
leftButton.isEnabled = webView.canGoBack
49+
}
50+
if (keyPath == #keyPath(WKWebView.estimatedProgress)) {
51+
progressBar.progress = Float(webView.estimatedProgress)
52+
rightButton.isEnabled = (webView.estimatedProgress == 1)
53+
}
54+
}
55+
56+
// Initialize WKWebView
57+
func setupWebView() {
58+
// set up webview
59+
webView = WKWebView(frame: CGRect(x: 0, y: 0, width: webViewContainer.frame.width, height: webViewContainer.frame.height))
60+
webView.navigationDelegate = self
61+
webView.uiDelegate = self
62+
webViewContainer.addSubview(webView)
63+
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
64+
65+
// settings
66+
webView.allowsBackForwardNavigationGestures = true
2267

68+
// init observers
69+
webView.addObserver(self, forKeyPath: #keyPath(WKWebView.isLoading), options: NSKeyValueObservingOptions.new, context: nil)
70+
webView.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: NSKeyValueObservingOptions.new, context: nil)
71+
}
72+
73+
// Initialize UI
74+
func setupUI() {
75+
// UI elements
76+
leftButton.isEnabled = false
77+
progressBar = UIProgressView(frame: CGRect(x: 0, y: 0, width: webViewContainer.frame.width, height: 50))
78+
progressBar.autoresizingMask = [.flexibleWidth]
79+
progressBar.progress = 0.0
80+
progressBar.tintColor = UIColor.green.withAlphaComponent(0.6)
81+
webView.addSubview(progressBar)
82+
}
83+
84+
// Initialize App and start loading
85+
func setupApp() {
86+
setupWebView()
87+
setupUI()
2388

89+
// load startpage
90+
let urlRequest = URLRequest(url: appUrl!)
91+
webView.load(urlRequest)
92+
}
93+
94+
// Cleanup
95+
deinit {
96+
webView.removeObserver(self, forKeyPath: #keyPath(WKWebView.isLoading))
97+
webView.removeObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress))
98+
}
2499
}
25100

101+
// WebView Event Listeners
102+
extension ViewController: WKNavigationDelegate {
103+
// didFinish
104+
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
105+
// set title
106+
navigationItem.title = webView.title
107+
// hide progress bar
108+
progressBar.isHidden = true
109+
}
110+
// didFailProvisionalNavigation
111+
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
112+
// show offline screen
113+
// @TODO
114+
let alert = UIAlertController(title: "You're offline", message: "didFailProvisionalNavigation", preferredStyle: .alert)
115+
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
116+
present(alert, animated: true, completion: nil)
117+
}
118+
// didFail
119+
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
120+
// show offline screen
121+
// @TODO
122+
let alert = UIAlertController(title: "You're offline", message: "didFail", preferredStyle: .alert)
123+
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
124+
present(alert, animated: true, completion: nil)
125+
}
126+
}
127+
128+
// WebView
129+
extension ViewController: WKUIDelegate {
130+
// handle links opening in new tabs
131+
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
132+
if (navigationAction.targetFrame == nil) {
133+
webView.load(navigationAction.request)
134+
}
135+
return nil
136+
}
137+
// restrict navigation to target host, open external links in Safari
138+
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
139+
if let requestUrl = navigationAction.request.url {
140+
if let requestHost = requestUrl.host {
141+
if (requestHost.range(of: allowedOrigin) != nil ) {
142+
decisionHandler(.allow)
143+
} else {
144+
decisionHandler(.cancel)
145+
if (UIApplication.shared.canOpenURL(requestUrl)) {
146+
UIApplication.shared.open(requestUrl)
147+
}
148+
}
149+
} else {
150+
decisionHandler(.cancel)
151+
}
152+
}
153+
}
154+
}

0 commit comments

Comments
 (0)