iOS UIWebView leaked - ios

class MyViewController: UIViewController {
#IBOutlet weak var webView: UIWebView?
override func viewDidLoad() {
super.viewDidLoad()
let url = NSURL(string: urlString)
let request = NSURLRequest(URL: url!)
SVProgressHUD.show()
webView?.loadRequest(request)
webView?.scrollView.header = MJRefreshNormalHeader(refreshingBlock: {
[weak self] in
if let strongSelf = self {
strongSelf.webView?.reload()
}}) }
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
SVProgressHUD.dismiss() } }
extension MyViewController: UIWebViewDelegate {
func webViewDidFinishLoad(webView: UIWebView) {
webView.scrollView.header.endRefreshing()
SVProgressHUD.dismiss() } func webView(webView: UIWebView, didFailLoadWithError error: NSError?) {
webView.scrollView.header.endRefreshing()
SVProgressHUD.dismiss() } }
The view controller was pushed by a navigation controller, when I pop it, I got leaks. In instrument.Leak I saw these.
#
Leaked Object # Address Size Responsible Library Responsible Frame NSMutableArray 1 0x137a6ddb0 48 Bytes UIKit -[_UIKeyboardTextSelectionGestureController init]
_UIKeyboardTextSelectionController 1 0x137a6e800 96 Bytes UIKit -[UIWebSelectionAssistant addNonEditableForceTextSelectionGestureRecognizersToView:]
_UIKeyboardBasedNonEditableTextSelectionGestureController 1 0x137a6dcd0 160 Bytes UIKit -[UIWebSelectionAssistant addNonEditableForceTextSelectionGestureRecognizersToView:]
#
I'm sure that the webView, myViewController were delayed, but when pop the myViewController, 4M increased and not release. Please help and thanks.
List item

According to an answer posted here, there is a workaround that if you set configuration.selectionGranularity to WKSelectionGranularityCharacter, the leaks stop:
let config = WKWebViewConfiguration()
config.selectionGranularity = .character //WKSelectionGranularityCharacter
let myWebview = WKWebview(frame: frame, configuration: config)
This worked for me, but then, when selecting text, there was no selection rectangle in the webview. This may or may not be a viable workaround in your case.
Edit I just noticed your question is for UIWebView, not WKWebView. It doesn't look like you can set this on UIWebView. I'll leave this answer for now since WKWebView folks googling this memory leak will probably find this thread...

Related

Instance member 'webView' cannot be used on type 'MyWebView(UIview)'

I am creating one SDK to get the url from user and load. So ai m creating my own class with WKWebview. But i am getting few issues about Instance member 'webView' cannot be used on type 'MyWebView(UIview)'
Code :
import Foundation
import WebKit
public class MyWebView: UIView, WKNavigationDelegate {
// initialize the view
var webView: WKWebView!
// load the view
private func loadView() {
webView = WKWebView()
webView.navigationDelegate = self
}
// get the url and load the page
public static func loadUrl(Url: String) {
MyWebView.webView.load(URLRequest(url: URL(string: Url)!))
}
}
In my loadUrl, what ever user sending i need to use that url and load the url. Same in my view controller will look like :
import UIKit
class ViewController: UIViewController {
var webView: MyWebView!
override func loadView() {
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
Any help would be great.
Your loadUrl function should not be static, since it needs access to an instance property, webView. Making the function non-static solves the issue.
Also a couple of minor improvements: don't force unwrap the URL init, since with an incorrect input that will crash. Use optional binding to safely unwrap it instead. I'd also suggest renaming the input argument label on loadUrl, since there's no point in having to right out loadUrl(Url:) every time you call the func, loadUrl( reads more naturally.
public func loadUrl(_ urlString: String) {
guard let url = URL(string: urlString) else { return }
webView.load(URLRequest(url: url))
}

I want to use "applicationWillEnterForeground", however my function requires an UIImageView and I can't call on it in AppDelegate?

I have an image on a website, and I want it to be put into a UIImageView, however I want it to refresh every time the application is launched.
I have the following code in a ViewController:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var image: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
get_image("WEBSITE.com/image.jpg", image)
}
func get_image(_ url_str:String, _ imageView:UIImageView)
{
let url:URL = URL(string: url_str)!
let session = URLSession.shared
let task = session.dataTask(with: url, completionHandler: {
(
data, response, error) in
if data != nil
{
let image = UIImage(data: data!)
if(image != nil)
{
DispatchQueue.main.async(execute: {
imageView.image = image
imageView.alpha = 0
UIView.animate(withDuration: 2.5, animations: {
imageView.alpha = 1.0
})
})
}
}
})
task.resume()
}
}
Since the image in WEBSITE.com/image.jpg is going to change often, I wan't the app to pull the image everytime it launches. I did some research, and was told to put the following code into my AppDelegate.
func applicationWillEnterForeground(_ application: UIApplication) {
ViewController().get_image("WEBSITE.com/image.jpg", image)
}
However, after the link, the "image" doesn't work. How do I reference the image in the AppDelegate file?
BTW, I get the following error message:
"Cannot convert value of type 'module' to expected argument type 'UIImageView'"
What do I do?
You can use the observer pattern to let ViewController know when the app will enter the foreground.
UIScene has a built in notification that you can simply observe from within the viewDidLoad of your view controller.
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(get_image), name: UIScene.willEnterForegroundNotification, object: nil)
}
The selector is the action taken whenever your view controller observes willEnterForegroundNotification. In order to use get_image as a selector you will also need to expose it to the Objective-C runtime by writing #Objc before the func keyword.

WKWebView is not getting intialized in swift 4 xcode 10

Could anyone help me in understanding why my webView is not getting initialized here. I am getting the following error because webView is nil.
Fatal error: Unexpectedly found nil while unwrapping an Optional value
What exactly I am missing here?
import UIKit
import WebKit
class MemoriesViewController: UIViewController, WKNavigationDelegate {
#IBOutlet weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear( animated )
let urlString:String = "https://www.apple.com"
let url:URL = URL(string: urlString)!
let urlRequest:URLRequest = URLRequest(url: url)
webView.load(urlRequest)
}
}
}
Screenshot for better clarity where the error is actually happening:
Add Webkit.Frameworks to Linked Framework and Libraries
You can then add the Outlet for WKWebView and use your code
import UIKit
import WebKit
class MyWebViewController: UIViewController {
#IBOutlet weak var myWV: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let urlString:String = "https://www.apple.com"
let url:URL = URL(string: urlString)!
let urlRequest:URLRequest = URLRequest(url: url)
myWV.load(urlRequest)
}
}
In Xcode 10, you can foll bellow the step:
Click the project
Go to build phase
Go to Link Binary with Libraries
Click add plus sing under Link Binary with Libraries
open a windows & search Webkit.framework
add & enjoy it
Show bellow image
The problem was my output was not connected to the storyboard. That's why #IBOutlet was not getting initialized.

WKNavigationDelegate Crashing App on Assignment

I'm working on a simple web wrapper application for iOS, and I'm having some issues with WKWebView and WKNavigationDelegate. I want to use the didFinishNavigation function from WKNavigationDelegate, so I can grab information from the URL query on navigation (namely a session GUID). My program launches correctly and loads my webpage when I comment out the "webView.navigationDelegate = self" line, but when I include that, my app crashes immediately with the following errors:
" -[UIWebView setNavigationDelegate:]: unrecognized selector sent to instance
0x7f8251e058f0"
"*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[UIWebView setNavigationDelegate:]: unrecognized selector sent to
instance 0x7f8251e058f0'"
I noticed that both of these error messages include "UIWebView," when I'm trying to use WKWebView, so I tried to use the "custom class" field on the webview from the identity inspector part of the storyboard, but when I try to run after that, I get "(lldb)." Any help/insight would be appreciated, I'm including my code below:
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
#IBOutlet weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
print("view did load")
webView.navigationDelegate = self
loadURL("http://mydomain/login.html")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
private func loadURL(targetURL: String){
if let url = NSURL(string: targetURL) {
let request = NSURLRequest(URL: url)
webView.loadRequest(request)
}
}
private func checkDomainGetSessionGUID(){
print ("we are here")
if let query = webView.URL?.query {
let queryArr = query.componentsSeparatedByString("&")
var parsedQuery : [String: String] = [:]
for field in queryArr {
let parts = field.componentsSeparatedByString("=")
parsedQuery.updateValue(parts[1], forKey: parts[0])
print ("key = \(parts[0]) and value = \(parts[1])")
}
}
else {
print ("didn't enter the if let")
}
}
func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
print ("delegate")
checkDomainGetSessionGUID()
}
}
PROCEDURE 1:
Step-1: Check UIElements that you are using in Storyboard design. if you had used Web view instead of using **WebKit View this error might come.Check your IBOutlet connection.
Step-2: Check your IOS deployment target, It must be IOS 11 and above because of UIWebKit View was released in IOS 8 but it contains a bug that was fixed in IOS 11 only. So set your deployment target 11 and above.
Step-3: Check your info.plist property. The following property should add in the listApp Transport Security Settings -> Allow Arbitrary Loads -> YES
PROCEDURE 2:
If in case you want deployment target as IOS 10 or below IOS 11 means you can implement like this
Step-1: Create a new UIViewcontroller with its swift ViewController file. And add below-given code to run your URL:
import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate {
var webView: WKWebView!
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
let myURL = URL(string:"https://www.apple.com")
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
}}
I hope this might be helpful to you...
I was getting this error inside (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
I removed the line [super webView:webView didFinishNavigation:navigation]; and everything worked as I expected, I'm not sure if it's hacky though.

Getting "Thread 1:EXC_BAD_ACCESS" error?

I am creating a simple web viewer using WKWebView and the Swift language. Here is my code.
import Cocoa
import WebKit
#NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate {
#IBOutlet var containerView : NSView! = nil
#IBOutlet weak var window: NSWindow!
func applicationDidFinishLaunching(aNotification: NSNotification) {
// Insert code here to initialize your application
var webView: WKWebView
webView = WKWebView() //Thread 1:EXC_BAD_ACCESS (code=1,address=0x20)
var url = NSURL(string:"http://www.google.com/")
var req = NSURLRequest(URL: url!)
webView.loadRequest(req)
}
func applicationWillTerminate(aNotification: NSNotification) {
// Insert code here to tear down your application
}
}
I'm now getting a "Thread 1:EXC_BAD_ACCESS" error on the webView = WKWebView() line when I try to run the application. How can I fix this?
If that's it's all your code, than I'd say you're missing to instantiate the WKWebView. Put a breakpoint on the self.webView!.loadRequest(req) line and check whether it's nil or not.
I've never worked with WKWebView, but I think that you need a view controller. Maybe this blog post can help you: Getting started with WKWebView using Swift in iOS 8
You forgot to initialise your WKWebView
var webView = WKWebView(frame: CGRectMake(0, 0, 320, 480))
var url = NSURL(string:"http://www.google.com/")
var req = NSURLRequest(URL: url)
webView.loadRequest(req)
I get this error whenever I try to use a brand new minimal class as a delegate. For example:
class MyDelegate: NSObject, UIWebViewDelegate { /* ... */ }
This does not happen when I try to use the default ViewController as a delegate. For example:
class ViewController: UIViewController, UIWebViewDelegate { /* ... */ }
I would suggest using the ViewController as a delegate until we get to the bottom of this.

Resources