I am new to Xcode
and I don't know how to set webview
in safe area
of iPhone X. I have gone through couple of various answers, but they didn't help. The only thing I know about this app is, the view is set programmatically. Below is my ViewController.swift
file.
import UIKit
import WebKit
import AVFoundation
class ViewController: UIViewController, WKScriptMessageHandler, WKNavigationDelegate, WKUIDelegate
{
var webView = WKWebView()
var containerView = WKWebView() //Footer Webview
override func loadView()
{
super.loadView()
}
override func viewDidLoad()
{
super.viewDidLoad()
let theConfiguration = WKWebViewConfiguration()
//Bind Swift and Javascript interface through MessageHandler IOSJSObject
theConfiguration.userContentController.add(self, name: "IOSJSObject")
/* Webview intialization Start */
webView = WKWebView(frame: CGRect(x: 0, y: 20, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height-65), configuration: theConfiguration)
containerView = WKWebView(frame: CGRect(x: 0, y: UIScreen.main.bounds.height-45, width: UIScreen.main.bounds.width, height: 45), configuration: theConfiguration)
/* Webview intialization End */
/* Error Page Code Start */
if(TestConnection.isConnectedToNetwork())
{
let url:URL = URL(string:"example.com")!
let request :URLRequest = URLRequest(url:url)
if let navController = self.navigationController
{
navController.popViewController(animated: true)
}
webView.load(request)
}
else
{
let path = Bundle.main.path(forResource: "error-connection", ofType: "html")
let text = try? String(contentsOfFile:path!, encoding: String.Encoding.utf8)
webView.loadHTMLString(text!, baseURL: nil)
}
/* Error Page Code End */
self.view.backgroundColor = UIColor.white
/* Container View Border Code Start*/
let myColor : UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1)
self.containerView.layer.borderColor = myColor.cgColor;
self.containerView.layer.borderWidth = 0.5
/* Container View Border Code End*/
/* Container View Button Home Back Refresh Code Start*/
let home = UIImage(named: "nptl-home.png")
let back = UIImage(named: "nptl-back.png")
//let refresh = UIImage(named: "nptl-refresh.png")
let homeButton = UIButton()
let backButton = UIButton()
//let refreshButton = UIButton()
homeButton.setImage(home, for: UIControlState())
homeButton.setTitleColor(UIColor.blue, for: UIControlState())
backButton.setImage(back, for: UIControlState())
backButton.setTitleColor(UIColor.blue, for: UIControlState())
//refreshButton.setImage(refresh, for: UIControlState())
//refreshButton.setTitleColor(UIColor.blue, for: UIControlState())
homeButton.frame = CGRect(x: (UIScreen.main.bounds.width/4)-50, y: 4, width: 37, height: 37)
homeButton.addTarget(self, action: #selector(ViewController.home(_:)), for: UIControlEvents.touchUpInside)
backButton.frame = CGRect(x: (UIScreen.main.bounds.width/1.33)+13, y: 4, width: 31, height: 37)
backButton.addTarget(self, action: #selector(ViewController.goBack(_:)), for: UIControlEvents.touchUpInside)
//refreshButton.frame = CGRect(x: UIScreen.main.bounds.width-60, y: 4, width: 48, height: 37)
//refreshButton.addTarget(self, action: #selector(ViewController.doRefresh(_:)), for: UIControlEvents.touchUpInside)
containerView.addSubview(homeButton)
containerView.addSubview(backButton)
//containerView.addSubview(refreshButton)
/* Container View Button Home Back Refresh Code End*/
self.view.addSubview(webView)
self.view.addSubview(containerView)
webView.navigationDelegate = self
webView.uiDelegate = self
webView.scrollView.bounces = false //No Bounce of Webview Screen From Top
if(TestConnection.isConnectedToNetwork())
{
checkUpdate()
}
}
func webView(_ webView: WKWebView,didFailProvisionalNavigation navigation: WKNavigation!,withError error: Error)
{
viewDidLoad()
}
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
{
if let messageBody:NSDictionary = message.body as? NSDictionary
{
print(" \(message.body)")
let myActionName = messageBody["actionName"] as! String
if myActionName == "shareApp"
{
let myShareAppSubject = messageBody["shareAppSubject"] as! String
let myShareAppUrl = messageBody["shareAppURL"] as! String
shareApp(myShareAppSubject,shareAppUrl:myShareAppUrl)
}
else if myActionName == "rateApp"
{
rateApp()
}
else if myActionName == "shareAppPage"
{
let myShareAppMessageSubject = messageBody["shareAppPageMessageSubject"] as! String
let myShareAppMessageURL = messageBody["shareAppPageMessageURL"] as! String
shareAppPage(myShareAppMessageSubject, shareAppPageURL: myShareAppMessageURL)
}
else if myActionName == "error"
{
viewDidLoad()
}
else if myActionName == "loadFromBaseUrl"
{
viewDidLoad()
}
}
}
func webView(_ webView: WKWebView,didStartProvisionalNavigation navigation: WKNavigation!)
{
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
/* Stop the network activity indicator when the loading finishes */
func webView(_ webView: WKWebView,didFinish navigation: WKNavigation!)
{
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: (@escaping (WKNavigationActionPolicy) -> Void))
{
if navigationAction.request.url?.scheme == "tel"
{
UIApplication.shared.openURL(navigationAction.request.url!)
decisionHandler(.cancel)
return
}
if navigationAction.request.url?.scheme == "mailto"
{
UIApplication.shared.openURL(navigationAction.request.url!)
decisionHandler(.cancel)
return
}
decisionHandler(.allow)
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Start Of Custom bottomfooter
@objc func doRefresh(_: AnyObject)
{
print("Refresh");
webView.reload()
}
@objc func goBack(_: AnyObject)
{
if webView.canGoBack
{
webView.goBack()
}
}
@objc func home(_: AnyObject)
{
//viewDidLoad()
if(TestConnection.isConnectedToNetwork())
{
let url:URL = URL(string:"example.com")!
let request :URLRequest = URLRequest(url:url)
if let navController = self.navigationController
{
navController.popViewController(animated: true)
}
webView.load(request)
}
else
{
let path = Bundle.main.path(forResource: "error-connection", ofType: "html")
let text = try? String(contentsOfFile:path!, encoding: String.Encoding.utf8)
webView.loadHTMLString(text!, baseURL: nil)
}
}
// End Of Custom bottomfooter
// rate app
func rateApp()
{
UIApplication.shared.openURL(URL(string: "https://itunes.apple.com/in/app/xyz/idxyz")!)
}
// share app
func shareApp(_ shareAppText: String,shareAppUrl: String)
{
let firstActivityItem = shareAppText
let secondActivityItem = shareAppUrl
print("printing firstActivityItem \(firstActivityItem)")
print("printing secondActivityItem \(secondActivityItem)")
let activityViewController : UIActivityViewController = UIActivityViewController(
activityItems: [firstActivityItem, secondActivityItem], applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView = self.view
self.present(activityViewController, animated: true, completion: nil)
}
//share product page
func shareAppPage(_ shareAppPageSubject: String, shareAppPageURL: String)
{
print("printing shareAppPageText \(shareAppPageSubject)")
let firstActivityItem = shareAppPageSubject
let secondActivityItem : URL = URL(string: shareAppPageURL)!
let activityViewController : UIActivityViewController = UIActivityViewController(
activityItems: [firstActivityItem, secondActivityItem], applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView = self.view
self.present(activityViewController, animated: true, completion: nil)
}
//session handling
func loadFromBaseUrl()
{
viewDidLoad()
}
func checkUpdate()
{
let nsObject : AnyObject! = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as AnyObject!
let localVersion = nsObject as! String
let numberFromString = (localVersion as NSString).doubleValue
print("ios App version "+localVersion)
let UpdateUrl:NSURL = NSURL(string: "example.com?actionname=MobileAppAjaxHandler.getIOSMobileAppVersion")!
let request:NSMutableURLRequest = NSMutableURLRequest(url:UpdateUrl as URL)
let queue: OperationQueue = OperationQueue()
// Sending Asynchronous request using NSURLConnection
NSURLConnection.sendAsynchronousRequest(request as URLRequest, queue: queue, completionHandler:{(response:URLResponse?, responseData:Data?, error: Error?) -> Void in
if error != nil
{
print(error.debugDescription)
}
else
{
//Converting data to String
let responseStr = NSString(data: responseData!, encoding: String.Encoding.utf8.rawValue)
print("response of remote Ios version ========"+(responseStr! as String))
let serverVersion = responseStr! as String
let numfromstr = (serverVersion as NSString).doubleValue
if numfromstr > numberFromString
{
let updateBox = UIAlertController(title: "Update App", message: "App update is available on app store", preferredStyle: UIAlertControllerStyle.alert)
updateBox.addAction(UIAlertAction(title: "Update", style: .default, handler: { (action:UIAlertAction) in
UIApplication.shared.openURL(URL(string: "https://itunes.apple.com/in/app/xyz/idxyz")!)
}))
updateBox.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action:UIAlertAction) in
}))
self.present(updateBox, animated: true, completion: nil)
}
}
})
}
override func viewWillAppear(_ animated: Bool)
{
print("inside view WillAppear for Portrait orientation");
super.viewWillAppear(animated)
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
}
override var shouldAutorotate : Bool
{
print("shouldAutorotate return false");
return false
}
override var supportedInterfaceOrientations : UIInterfaceOrientationMask
{
print("supportedInterfaceOrientations");
return UIInterfaceOrientationMask.portrait
}
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void)
{
let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (_)-> Void in
completionHandler()
}))
self.present(alert, animated: true, completion: nil)
}
func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void)
{
let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (_)-> Void in
completionHandler(true)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (_)-> Void in
completionHandler(false)
}))
self.present(alert, animated: true, completion: nil)
}
}
My Xcode version is 9.2 and this is the only file i have got. Any small help will be appreciated
The safeAreaInsets property means that screen can be covered from all sides not only at the top and the bottom. When the iPhone X was presented it become clear why we would need the left and right insets. The iPhone X has the top and the bottom safe area insets in portrait orientation. Left, right and bottom insets in landscape orientation.
In iOS 11 the UIViewController topLayoutGuide and the bottomLayoutGuide properties have been replaced by the new safe area properties in UIView: The safeAreaInsets property means that screen can be covered from all sides not only at the top and the bottom.
Like iOS 11, Android P includes features to determine the safe area of the screen and work with the given insets. The new DisplayCutout class lets you find out the location and shape of the non-functional areas where content shouldn’t be displayed. To determine the existence and placement of the cutouts areas, use the getDisplayCutout () method.
When you change the additional safe area insets or safe area insets are changed by the system, the appropriate methods in UIView and UIViewController are called Additional safe area insets also can be used to test how your app supports iPhone X.
Try to do autolayout
using the layout anchors
instead of frame
to your custom WKWebView
.
let containerViewHeight: CGFloat = 45
webView = WKWebView()//(frame: CGRect(x:0, y: 0, width:screenWidth, height:screenHeight))
view.addSubview(webView)
webView.translatesAutoresizingMaskIntoConstraints = false
webView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0.0).isActive = true
webView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0.0).isActive = true
webView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0.0).isActive = true
webView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -containerViewHeight).isActive = true
containerView = WKWebView()//(frame: CGRect(x:0, y: 0, width:screenWidth, height:screenHeight))
view.addSubview(containerView)
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0.0).isActive = true
containerView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0.0).isActive = true
containerView.topAnchor.constraint(equalTo: webView.bottomAnchor, constant: 0.0).isActive = true
containerView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0.0).isActive = true
For the glance of safeArea region I've added the below image.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With