This application is modifying the autolayout engine from a background thread, - uitableview

I wonder if you can help as I am getting this error.
2016-07-17 20:13:01.312 ShortGameGolfAcademy[17843:6735678] This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes. This will cause an exception in a future release.
Stack:(
Now I think this has something to do with an embed YouTubeVideo code.
import UIKit
class ControlBackSwingViewController: UIViewController {
#IBOutlet weak var videoView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
let youTubeUrl = "https://www.youtube.com/embed/TNY9xpW0idk"
videoView.allowsInlineMediaPlayback = true
videoView.loadHTMLString("<iframe width=\"\(videoView.frame.width)\" height=\"\(videoView.frame.height)\" src=\"\(youTubeUrl)\" frameborder=\"0\" allowfullscreen></iframe>", baseURL: nil)
// Do any additional setup after loading the view.
}
Now I am going from a Static UITableView to a WebView in a Storyboard.

Try putting the code in question in this code block:
dispatch_async(dispatch_get_main_queue(), { () -> Void in
print("This is run on the main queue, after the previous code in outer block")
})

Related

How to make transparent background WKWebView in Swift

I want a transparent web page in swift, so I have tried the below code according to this answer. Still, I am not getting a transparent web page. nothing changes in webview colour.. may I know why??
where am I going wrong? please help me in below code.
Total code:
import UIKit
import WebKit
class WebviewViewController: UIViewController {
#IBOutlet weak var testWebView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
guard let url = URL(string: "https://developer.apple.com/swift/") else { return }
let request = URLRequest(url: url)
testWebView.load(request)
// Do any additional setup after loading the view.
self.testWebView = WKWebView()
self.testWebView!.isOpaque = false
self.testWebView!.backgroundColor = UIColor.clear
self.testWebView!.scrollView.backgroundColor = UIColor.clear
}
}
Please help me with the code.
the code to make transparent background is as follow what you already added.
self.testWebView!.backgroundColor = UIColor.clear
now question is you added right code already then why you are not getting reliable output ..?
Also , if you try
self.testWebView!.alpha with any value, it will affect all of WebPages as WkWebView is a single view and changing it's alpha will also affect the components within...
it happened because the page you load in WebViewController has some HTML and CSS code, you make your WebViewController transparent but because of that HTML &CSS you can't see it's transparency as each webpage has it's own background color settings (which is merely impossible to change for each webpage)
I hope you will understand and it will help you ...:)
as I see, you use storyboard (#IBOutlet) and you can use Storyboard for setting your WKWebView:
And about code. This is enough for the result. You shouldn't set again self.testWebView = WKWebView(), because you use storyboard and you can set isOpaque with storyboard. As result:
class ViewController: UIViewController, WKNavigationDelegate {
#IBOutlet var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
webView.navigationDelegate = self
let url = URL(string: "https://developer.apple.com/swift/")!
webView.load(URLRequest(url: url))
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
let js = "(function() { document.body.style.background='transparent'; })();"
webView.evaluateJavaScript(js) { (_, error) in
print(error)
}
}
}
and evaluateJavaScript helped to add transparency for background:

Kingfisher iOS image not loading

I am trying to dynamically set a UIImageView using Kingfisher. The context is there is a TableView on the previous screen of different selectable rows and then when the row is selected a details UIView shows which has more information, including an image. I have gone to the Kingfisher documentation and found that the declaration belongs in the viewDidLoad as i have it but i still cannot get the image to load. I have also verified with debugging that the URL being passed to the Kingfisher is a link to a picture. I am thinking this may have to do with the image being set on a background thread but i am unsure how to fix that if that is the case. I have tried moving the implementation of the Kingfisher to the viewWillAppear and viewDidAppear functions and they still do not display the image even after an extended amount of wait time
Here is my code with some unrelated functionality removed.
import UIKit
import Kingfisher
class DetailsViewController: UIViewController {
#IBOutlet weak var thumbnail: UIImageView!
var thumbnailURL: URL?
override func viewDidLoad() {
super.viewDidLoad()
self.thumbnail.kf.setImage(with: thumbnailURL)
...................................................
// self.thumbnail.image = UIImage(named: "image1")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
kd02 - I have found the answer to my question. When you asked if it was http or https i remembered that you have to enable http in xcode 9 now because of the security enhancement. I did that and now it works.
Try something like this
import UIKit
import Kingfisher
class DetailsViewController: UIViewController {
#IBOutlet weak var thumbnail: UIImageView!
var thumbnailURL: URL?
override func viewDidLoad() {
super.viewDidLoad()
if let url = self.thumbnailURL {
self.thumbnail.setImage(with: url)
}
}
}
I have feeling the optional URL is causing the problem.

Why my indicator view is not showing?

Using swift3 with xcode8
Below is my viewconroller.swift
class ViewController: UIViewController {
#IBOutlet weak var YahooWebview: UIWebView!
#IBOutlet weak var activity: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
let YURL = URL(string: "http://www.yahoo.com")
let YURLRequest = URLRequest(url: YURL!)
YahooWebview.loadRequest(YURLRequest)
}
}
func webViewDidStartLoad(YahooWebview: UIWebView) {
activity.startAnimating()
}
func webViewDidFinishLoad(YahooWebview: UIWebView) {
print("show indicator")
activity.stopAnimating()
}
Why my indicator is not showing when webview is loading?
I can not even see string "show indicator" from my log in Xcode.
You need to set your class as the delegate of UIWebView as
YahooWebview.delegate = self
Check my answer to get details regarding delegates and delegation pattern.
Note from apple developer: In apps that run in iOS 8 and later, use the
WKWebView class instead of using UIWebView. Additionally, consider setting the WKPreferences property javaScriptEnabled to false if you render files that are not supposed to run JavaScript.
There can be two problems as mentioned in comments.
Both can be solved in your Stroyboard/xib file.
Your UIActivityIndicatorView is may be hidden behind UIWebView. Just change the position of the view so that it comes above in the view heirarchy.
You may not have set delegate property of UIWebview class as your ViewController. Right click on webview and check. This needs to be set as you are animating the activity indicator view inside delegate methods.

UIWebView Delegate not changing other views

I have a webView in a simple application which is under a UIImageView. I intend on displaying the UIImageView until webView loads some data and fires a method in the web view delegate. Webview loads the data, delegate method is called fine. However, I am having trouble manipulating other views like the UIImageView.
Here is my code;
class ViewController: UIViewController,UIWebViewDelegate {
//contains the imageView and activityWorkingIndicator
#IBOutlet weak var splash_view: UIView!
#IBOutlet var contentWebView: UIWebView!
//Contains the Webview and other views to be displayed after the splash his hidden
#IBOutlet weak var splash_view_not: UIView!
override func viewWillAppear(animated: Bool)
{
contentWebView?.scrollView.bounces = false;
contentWebView?.delegate = self
let url = NSURL(string: "http://localhost/something/");
let request = NSURLRequest(URL: url!);
contentWebView?.loadRequest(request);
}
....
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if let scheme = request.URL?.scheme {
if scheme == "myRequestScheme"{
let task : String = (request.URL?.host)!;
switch task {
case "systemReady":
print("checkpoint 1");//works fine
splash_view?.hidden = true;//no effect at all
splash_view_not?.hidden = false;//no effect at all
print("checkpoint 2");//works fine
break;
default:
break
}
}
}
return true;
}
}
What am I missing here?
It looks like you are using Auto Layout. If that is the case, using .hidden has more implications than you think. If you are calling it in a method after the view has already been loaded, you need to work with constraints instead of hidden. Some people create constraint outlets and set them to active to hide things. Some people set alphas and bring subviews to front to hide things, etc.
I believe this is the preferred way:
http://candycode.io/hiding-views-with-auto-layout/
And here is a stack overflow thread with A LOT of information on your best options to hide things with AutoLayout:
AutoLayout with hidden UIViews?
You should hide or show any control in delegate method on main thread.
Use like this
DispatchQueue.main.async {
splash_view_not?.hidden = false
}

iOS 8 Free Memory after WebView (swift)

Currently i got a small problem with WebViews that dont release there memory usage in time, i m calling some webviews (the user can open them switch back to a map (via Tabbar) and open a new one),
Everytime a WebView is called it use up to 30MB RAM, so after 10 WebViews the App runs into a memory warning, so i m looking for a way (as i found in other Posts there is no way caus it handled automatic) to release the memory after switching back to the map from the webview.
This is how i call my WebView
import UIKit
class ViewController_webView: UIViewController {
/* ################################################## IBOutlets ################################################## */
#IBOutlet weak var webView: UIWebView!
#IBOutlet weak var TBB_shop: UITabBarItem!
#IBOutlet weak var activity: UIActivityIndicatorView!
/* ################################################## Home Button ################################################## */
#IBAction func BThome(sender: AnyObject) {
var shopurl = "http://google.com"
let webviewURL = NSURL(string: shopurl)
let request = NSURLRequest(URL: webviewURL)
webView.loadRequest(request)
}
/* ################################################## ViewDidLoad ################################################## */
override func viewDidLoad() {
super.viewDidLoad()
var TBB_shop_img = UIImage(named: "TabbarShopping.png") as UIImage
TBB_shop.selectedImage = TBB_shop_img
}
/* ################################################## MemoryWarning ################################################## */
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
println("Memory Warning")
}
/* ################################################## viewWillAppear ################################################## */
override func viewWillAppear(animated: Bool) {
var shopurl = "http://google.com"
let webviewURL = NSURL(string: shopurl)
let request = NSURLRequest(URL: webviewURL)
webView.loadRequest(request)
}
/* ################################################## Activity Indicator ################################################## */
func webViewDidStartLoad(_ : UIWebView){activity.startAnimating()}
func webViewDidFinishLoad(_ : UIWebView){activity.stopAnimating()}
}
Is there anyway to use the
override func viewDidDisappear(animated: Bool) {
<#code#>
}
to release the memory usage of a webview? Or anyway to reduce the usage of memory?
From your code I deduce that the webView is in a nib.
To reduce the memory footprint, you might want to try creating and removing the webView in viewWillAppear and viewWillDisappear, respectively.
This would mean that you might have to re-load the content if the user were to go back to it. Annoying from the user perspective.
Releasing memory can depend on how you are bringing up the view - here is a modal presentation of a view controller - this will not release memory of a previously loaded view controller:
let vc = self.storyboard!.instantiateViewControllerWithIdentifier("WebViewController") as WebViewController
let navigationController = UINavigationController(rootViewController: vc)!
self.presentViewController( navigationController, animated: true, completion: nil)
Below is a case where the rootViewController is replaced with the new controller - in this case the rootViewController value is changed - so the original view controller (if one was loaded before) reference count goes down to 0 and should be removed from memory, in theory:
let vc = self.storyboard!.instantiateViewControllerWithIdentifier("WebViewController") as WebViewController
let navigationController = UINavigationController(rootViewController: vc)!
let window = UIApplication.sharedApplication().windows[0] as UIWindow
window.rootViewController = navigationController
I tried the latter case in a code situation like what is described in the question. I saw an improvement in memory releasing, however I have to admit that the memory did not go back where I started from - don't know why. I hope somebody has a better solution.

Resources