Swift webView empty spaces on scroll - swift

When I'm scrolling up or down and no space for scroll, there are empty spaces. How can I fix it?
Empty places I marked with a red lines.
code
class ViewController: UIViewController {
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
let aurl = URL(string: "https://www.google.com")
let arequest = URLRequest(url: aurl!)
webView.loadRequest(arequest)
}
}

I fix it.
webView.scrollView.bounces = false

Related

Wkwebview overlying and hiding the toolbar

I am using wkwebview to show a webpage but it is overlaying the toolbar. If I remove
view = webView Then the toolbar can be seen but not the webpage. Been going around in circles with this and tried several possible solutions in other threads but nothing is working. Here is my code...
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate{
var webView: WKWebView!
override func loadView() {
webView = WKWebView()
webView.navigationDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string:"website address")!
webView.load(URLRequest(url: url))
webView.allowsBackForwardNavigationGestures = true
let webConfiguration = WKWebViewConfiguration()
webConfiguration.allowsInlineMediaPlayback = true
}
}

Need help to reload WKWebView from tabbed navigation in Swift

I'm trying to make this reload when a user clicks on the tab. I tried a simple reload but didn't work.
#IBOutlet weak var TabOne: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "https://www.google.com")
let urlRequest = URLRequest(url:url!)
TabOne.load(urlRequest)
}
Move the reload code into the viewWillAppear(_:)
as viewDidLoad() will only be called once in the view controller life cycle, while viewWillAppear(_:) will be called every time the view is going to appear on the screen.
This is the code that ended up working.
import UIKit
import WebKit
class FirstViewController: UIViewController {
#IBOutlet weak var TabOne: WKWebView!
override func viewWillAppear(_ animated: Bool) {
let url = URL(string: "https://www.google.com")
let urlRequest = URLRequest(url:url!)
TabOne.load(urlRequest)
}
}

Grab loaded webpage URL? WKWebView macOS

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
self.urlText.stringValue = String(describing: webView.url!)
}
This does not work 100% of the time.
An example would be when I navigate to reddit. I click a thread and it changes URL which is fine, but if I click the reddit home button, it doesn't change URL to www.reddit.com even after it is 100% loaded.
Any help is appreciated.
What else is going on in your view controller? I'm not able to reproduce your problem with the code below. Have you tried this in an isolated project?
import Cocoa
import WebKit
class ViewController: NSViewController {
#IBOutlet weak var webView: WKWebView!
#IBOutlet weak var urlLabel: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
let req = URLRequest(url:
URL(string: "https://reddit.com")!)
webView.load(req)
}
#IBAction func getUrlClicked(_ sender: Any) {
guard let url = webView.url else { return }
urlLabel.stringValue = url.absoluteString
print("url: \(String(describing: webView.url!))")
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}

Crash while unwrapping an Optional Value

I am getting an error. It is returning nil on a DispatchQueue call.
DispatchQueue.main.async {
self.headerImageView.image = image // <- CRASH
}
Turns out that this is where I am getting a crash.
headerImageView is just a variable which is not connected to the storyboard via IBOutlet. Here is the entire code:
import UIKit
import WebKit
let offset_HeaderStop:CGFloat = 40.0
let offset_B_LabelHeader:CGFloat = 95.0
let distance_W_LabelHeader:CGFloat = 35.0
class MovieDetailsViewController: UIViewController, UIScrollViewDelegate {
var movie: Movie?
var urlBuilder = MovieUrlBuilder()
var config = TMDBConfiguration()
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var headerView: UIView!
#IBOutlet weak var headerLabel: UILabel!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var genreLabel: UILabel!
#IBOutlet weak var ratingLabel: UILabel!
#IBOutlet weak var releaseLabel: UILabel!
#IBOutlet weak var descriptionText: UITextView!
#IBOutlet weak var trailerContainerView: UIView!
#IBOutlet weak var trailerLabel: UILabel!
#IBOutlet weak var videoContainer: WKWebView!
var headerImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
}
override func viewDidAppear(_ animated: Bool) {
headerImageView = UIImageView(frame: headerView.bounds)
headerImageView.image = UIImage(named: "Poster")
headerImageView.contentMode = .scaleAspectFill
headerView.insertSubview(headerImageView, belowSubview: headerLabel)
headerView.clipsToBounds = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
fetchPopularMovies()
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offset = scrollView.contentOffset.y
var headerTransform = CATransform3DIdentity
if offset < 0 {
let headerScaleFactor: CGFloat = -(offset) / headerView.bounds.height
let headerSizeVariation = ((headerView.bounds.height * (1.0 + headerScaleFactor)) - headerView.bounds.height)/2.0
headerTransform = CATransform3DTranslate(headerTransform, 0, headerSizeVariation, 0)
headerTransform = CATransform3DScale(headerTransform, 1.0 + headerScaleFactor, 1.0 + headerScaleFactor, 0)
headerView.layer.transform = headerTransform
} else {
headerTransform = CATransform3DTranslate(headerTransform, 0, max(-offset_HeaderStop, -offset), 0)
let labelTransform = CATransform3DMakeTranslation(0, max(-distance_W_LabelHeader, offset_B_LabelHeader - offset), 0)
headerLabel.layer.transform = labelTransform
}
headerView.layer.transform = headerTransform
}
override var preferredStatusBarStyle: UIStatusBarStyle{
return UIStatusBarStyle.lightContent
}
private func fetchPopularMovies() {
if let poster = movie?.backdropPath {
let baseURL = URL(string: config.baseImageURL)!
let url = baseURL.appendingPathComponent("w500").appendingPathComponent(poster)
let request = URLRequest(url: url)
let task = urlBuilder.session.dataTask(with: request) {(data, response, error) in
do {
if let image = UIImage(data: data!) {
DispatchQueue.main.async {
self.headerImageView.image = image // <- CRASH
}
}
}
}
task.resume()
}
}
}
Thank you for the support!
You are initializing the image view in viewDidAppear which will be called after viewWillAppear where the image view is populated. Despite the asynchronous task it's not guaranteed that the view is initialized before being populated.
I recommend to initialize the image view lazily, the benefit is that the property is non-optional and it's initialized once when it's accessed the first time.
lazy var headerImageView: UIImageView = {
let view = UIImageView(frame: self.headerView.bounds)
view.image = UIImage(named: "Poster")
view.contentMode = .scaleAspectFill
self.headerView.insertSubview(view, belowSubview: self.headerLabel)
view.clipsToBounds = true
return view
}()
Your async call is located in fetchPopularMovies, which is called at viewWillAppear. You initialise your image view in viewDidAppear, which is called after viewWillAppear.
Basically, headerImageView is nil.
"But I put the call in an async block! So viewDidAppear should have been called already when I set the image view's image, right?" you said.
Well, relying on async to say "I want this thing to run after a certain method returns" is not a good idea. It is not always guaranteed to do that.
To fix this, you need to initialise header image view before fetchPopularMovies is called. You can put it in viewDidLoad for example.

How to Disable all the Links from webView once it is loaded?

I am making simple web based application where I want to disable all the links when the page is loaded fully into the webView and for that I also tried this answer. But when I try this my UIActivityIndicatorView is stopped displaying.
This is my code:
import UIKit
class ViewController: UIViewController,UIWebViewDelegate {
#IBOutlet var webView: UIWebView!
#IBOutlet weak var Activity: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
Activity.hidden = true
var myString = "https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_456"
let myURL = NSURL(string: myString)
let myReq = NSURLRequest(URL: myURL!)
webView.loadRequest(myReq)
webView.delegate = self
}
func webViewDidStartLoad(webView: UIWebView){
var activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .Gray)
var activityBarButtonItem = UIBarButtonItem(customView: activityIndicator)
navigationItem.rightBarButtonItem = activityBarButtonItem
activityIndicator.startAnimating()
}
func webViewDidFinishLoad(webView: UIWebView){
navigationItem.rightBarButtonItem = nil
}
}
Can anybody tell me how can I achieve that?
Thanks In advance!
What about displaying a transparent view over it?
EDIT
Try adding a new gesture recognizer to it and tell it to do nothing for taps?
let recognizer = UITapGestureRecognizer(target: self, action:Selector("handleTouch:"))
recognizer.delegate = self
webView.addGestureRecognizer(newTap)
func handleTouch(recognizer:UIPanGestureRecognizer) {}
Theres a great tut on gestures in swift here Swifty_Gestures