WKWebview goes blank after device rotation - ios

I'm making a scrollview with multiple subviews, includes collectionView, webView, and normal UIview. As far as Ive read through, it is not recommended to put webview inside a scrollview. But it is still ok to add webview as subview inside the scrollview.
The requirement is that the webview will dynamically load the content onClick. So, at first, there was a bit of issue trying to dynamically resize the height of the webview as per the content size. The height gets added extra pixels after every rotation. But somehow managed to make it work using webview.sizeToFit() in the viewDidLayoutSubviews().
But now the problem is that, the content of the webview disappears after every 2 rotation of the device. The content should still be there because the webview's frame size didnt change after roation, just the texts inside disappear.
There is not other error as to why the webview is showing blank for after rotated.This is my viewdidlayoutsubview.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
webView.frame.size.height = 1
webView.frame.size = webView.sizeThatFits(.zero)
webView.sizeToFit()
}
Not sure how to solve.

I will just answer myself here, since the solution last time was still working well for this. Refresh the view layouts on in the override func viewWillTransition. As per apple's doc, "UIKit calls this method before changing the size of a presented view controller's view". So Ive refreshed all the subview's before changing the orientation.
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator){
super.viewWillTransition(to: size, with: coordinator)
//code to refresh the views
}

Just add this line below wkwebview code
i named var = webView so,
webView.autoresizingmask = [.flexiblewidth,.flexibleheight]
hope it works.

Related

What happens to WKWebView when scrolled out of bounds

I'm using a paged scroll view displaying different web views as pages. The scroll view has set clipsToBounds = false to allow the display of previous and following pages in the scroll view.
When scrolling through the pages, there is one exact moment, where the WKWebViews content becomes completely invisible. This happens exactly at the moment, where the web view leaves the bounds of the scroll view (see below). On some websites, the visible content out of the bounds is different to the actual content.
These problems only occur when using WKWebView instead of UIWebView (Everything works as intended with UIWebView).
Has someone experienced similar issues with the WKWebView and has a solution for them?
EDIT:
There is a now a sample project on Github, where you can experience the bug and play around with it:
WKWebView test project
To figure it out i think you need to use UICollectionView.
The cell should exist with WKWebView while it will be on screen.
1) You need to place it like Here
And next problem will be to make content pageble.
2) To do it right you need to add UIScrollView over your collection like Here
3) After, make your UIScrollView pageble and write in viewdidload:
collectionView.addGestureRecognizer(scrollView.panGestureRecognizer)
4) After you receive models for showing in UICOllectionView - update your contentSize of UIScrollView like
scrollView.contentSize = CGSize(width: (models.count*(cellWidth+cellIndent) + sectionIndent * 2), height: cellHeight)
5) Implement UIScrollViewDelegate
extension YourVC: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == self.scrollView {
collectionView.contentOffset = scrollView.contentOffset
} else if scrollView == self.collectionView {
self.scrollView.contentOffset = scrollView.contentOffset
}
}
}
Thats it. Happy coding =)
WKWebView is designed to be more performant than UIWebView. It will stop running some parts of a webpage or stop rendering it completely if it is not on top of the view hierarchy. The problem here is that once the webpage is out of the bounds of the scrollview, WKWebView does not consider itself to be on screen even though it is visible by virtue of setting clipsToBounds = false.
The easiest thing to do would be to use UIWebView. If for some reason you need WebKit, consider adjusting you paging code so your scrollview spans the entire view controller.

How to keep correct layout for UIStackView's subview after the subview re-appears after device rotation?

Hi have a UIStackView for which I have deselected the Installed property for compact heights:
Interface Builder shows the element in portrait mode and hides the element in landscape mode. When I run the app in the iPhone simulator, initially in portrait mode the element is rendered correctly (second row of buttons):
The element disappears after rotating right. But after rotating left again back to portrait mode, the element is rendered incorrectly (see top left of the screen):
Do I need to programmatically take care of the element's layout after is appears again? If so, where can I find documentation to help get me started with this?
Comparing the parent view's subviews and arrangedSubviews properties indicates that iOS adds the view to the former, but not to the latter. (This is when iOS takes care of adaptive layout based on variations of the 'installed' checkbox for different traits, as specified in the attribute inspector.)
So this specific subview needs to be inserted back into the arranged subviews. I added this override to the main view controller (layout is the stack view, secondaryRow is the row of buttons that is removed/added depending on the screen's height):
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let index = layout.subviews.index(of: secondaryRow) {
layout.insertArrangedSubview(secondaryRow, at: index)
}
}
I'm sure it can be generalised, perhaps to synchronise all UIStackViews subviews and arrangedSubviews when the layout has changed.
I think you need to redraw the views again when you change the orientation by overriding viewWillTransistion method.
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
// When orientations changes draw the layout again
// by invalidating the current layout of the views
// For Example, if I want to redraw for UIStackView I will use
stackView.setNeedsLayout()
}

UIWebView on scrollView resize the height

Ihave a UIWebView on a scroll view. I want to disable scrolling for my web view. It should scroll when the main scroll view scrolling.But my problem is when the webview content is long I cant see the bottom lines. I am resizing the webview like this.
func webViewDidFinishLoad(webView: UIWebView) {
let url = NSBundle.mainBundle().URLForResource("Script", withExtension: "js")!
let javascript = try! String(contentsOfURL: url)
self.webvw.stringByEvaluatingJavaScriptFromString(javascript)
var frame:CGRect=webView.frame
frame.size.height=1
let fittingSize:CGSize = webView.sizeThatFits(CGSizeZero)
frame.size=fittingSize
self.webvw.frame=frame
self.mainScroll.contentSize=CGSizeMake(self.view.frame.size.width, self.webvw.frame.origin.y+self.webvw.frame.size.height)
self.hud.hide(true, afterDelay: 1.0)
}
But still same. Didn't help me that. How can I solvethis pronlem.
Please help me.
Thanks
WebViews have built in scrolling. If you want to scroll through WebView's content, you would not need to use UIScrollView.
However, if you choose to do so, (I would not recommend), then you must set
you UIWebView's instance's scrollEnabled to false.
And then you will have to track you UIScrollView's content offset, and match UIWebView's scroll's content offset to that value. Doesn't seem like a good idea though. You can just scroll webview itself (without having to use UIScrollView).
And to get UIScrollView's content offset, you must override didScroll method of scrollView delegate.

Strange behavior when setting height of a table header view

I am trying to make my table header equally high as its contents. It seems impossible to do this in storyboard so I tried to programmatically set the height upon loading the view. Yet the table header is much higher than its subviews while the frame size is said to be the same.
I did this in my viewDidLoad function.
override func viewDidLoad() {
super.viewDidLoad()
ongoingOrderTableView.backgroundColor = UIColor.blueColor()
tableHeader.backgroundColor = UIColor.redColor()
tableHeader.frame.size.height = 440
print(tableHeader.frame.size)
//(560.0, 440.0)
print(qrLabel.frame.size)
//(54.0, 21.0)
print(qrImage.frame.size)
//(440.0, 440.0)
}
Printed result showed that the settings are correct.
The UI on simulator is as below:
Can somebody explain why did this happened and how to fix that?
When using auto layout, iOS will keep a 600 * 600 screen size until func viewDidLayoutSubviews() is called. Hence you should do your dynamic adjustment of layouts in viewDidLayoutSubviews() rather than viewDidLoad().
I put the print(tableHeader.frame.size) in viewDidLayoutSubviews() as well and the result is (374.0, 501.0). And when I adjust header height in this function it all turned out correct.
Set the height of the table header view in viewDidLayoutSubviews().
To debug the issue , add a breakpoint in viewDidLayoutSubviews() and check the header height.
In my experience this happens in case you dont add the tableHeaderView from storyboard.
This is the issue with your navigation bar,
Try switching your top bar to Opaque Navigation Bar, Select NavigationController on your storyboard > Simulated Metrics > Top Bar > Opaque Navigation Bar
For example having image view :
Default/ Transclucent :
Opaque :

Frame change of table view cell's subview won't take place until view did appear

I want to change a UITableViewCell's subview when it is being setup in the cellForRowAtIndexPath with the following code:
cellSubView.center = CGPointZero
Printing out the frame's coordinates shows, that the frame updates successfully, however the view is still displayed in the position that was given in the interface builder.
Overriding the viewDidAppear function with the following code would resolve this issue:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.tableView.reloadData()
}
But this will result in blinking: the table view already did appear when I change one of its cells' subview's position.
How is it possible to change the frame before the view did appear?
If you used autoLayout check if it's creating the constraints automatically.
If yes, then you can change the constants of these constraints instead.
If you are not using autoLayout, call layoutIfNeeded and see if that changes anything.
My bet though is on autoLayout creating constraints automatically.

Resources