Hi!
I have a rather complicated SwiftUI browser app with a WKWebView. There is an option to reload the website after a configurable amount of time. Starting with iOS 18, the app crashes after repeated reloads. How many reloads that are required depends on the device, sometimes 100, sometimes 1000.
Reloading is done via a timer that triggers the following code on the main thread:
let request = URLRequest(url: url, cachePolicy: policy)
self.parent.webView.load(request)
The URL is configurable and cachePolicy can be either .reloadIgnoringLocalAndRemoteCacheData or .useProtocolCachePolicy
How the crash affects the device also differs from device to device and from time to time. I have suffered from the following crashtypes:
App is killed
App is killed and Safari also stops working
App is killed and the whole OS is really slow
The WKWebView stops loading and hangs at 20%.
The device is rebooted
My app has an option to disable cache. Cache is disabled by setting cachePolicy to .reloadIgnoringLocalAndRemoteCacheData and by removing all cache in a rather complicated way.
Basicly i'm doing something like this:
dataStore.removeData(ofTypes: types, modifiedSince: Date.distantPast, completionHandler: nil)
if let klazz = NSClassFromString("Web" + "History"),
let clazz = klazz as AnyObject as? NSObjectProtocol {
if clazz.responds(to: Selector(("optional" + "Shared" + "History"))) {
if let webHistory = clazz.perform(Selector(("optional" + "Shared" + "History"))) {
let o = webHistory.takeUnretainedValue()
_ = o.perform(Selector(("remove" + "All" + "Items")))
}
}
}
if let cachesPath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first {
let contents = (try? FileManager.default.contentsOfDirectory(atPath: cachesPath)) ?? []
for file in contents {
if foldersToDelete.contains(file) {
let path = cachesPath.appending("/").appending(file)
do {
try FileManager.default.removeItem(atPath: path)
} catch {
print("Can't delete cache file: \(path), error: \(error.localizedDescription)")
}
}
}
}
The cache state affects the intensity of the crash. Disabling the cache shortens the time the app is working, while enabling the cache reduces the intensity of the bug.
Based on my investigation, I suspect that loading a website in a WKWebVew leaks memory in iOS 18. If the whole website needs to be requested (= caching off), it results in a more significant memory leak and a faster crash time.
Is this a known issue? Am I doing something wrong? Is there a potential workaround?
Post
Replies
Boosts
Views
Activity
I have a simple app with a WKWebView. When running on iOS 9.3, the memory usage stays around 5 Mb with is expected since WKWebView runs in a separate process. But memory usage for "other processes" goes high after a couple of navigations, especially on heavy pages. When the memory usage reaches its threshold, the app gets two memory warnings and then gets terminated. The debugger gives no output. I find this behavior unexpected since one of the features with WKWebView is that the app won't terminate when WKWebView runs out of memory. It should instead kill the WKWebView process and trigger webViewWebContentProcessDidTerminate. But webViewWebContentProcessDidTerminate is never called.This is my code:import UIKit
import WebKit
class MyAwsomeWebViewController: UIViewController, WKNavigationDelegate {
var page:WKWebView! = WKWebView()
@IBOutlet weak var WKBaseView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
page.navigationDelegate = self
if let url = URL(string: "https://hitta.se") {
let request = URLRequest(url: url)
page.load(request)
}
}
override func loadView() {
self.view = page
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
print("**** MEMORY WARNING! ****")
}
func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
print("*** Terminate WebView Process ***")
}
}Why does my app get terminated and how can I prevent this?