Explore the integration of web technologies within your app. Discuss building web-based apps, leveraging Safari functionalities, and integrating with web services.

General Documentation

Post

Replies

Boosts

Views

Activity

How can I initiate a new URL request using an already loaded WKWebView?
I have opened a WKWebView with "https://www.google.com", for example. After that, I put my app in the background. When I try to open a new URL request in the same web view with a new link, like "https://www.youtube.com", by redirecting the app, it doesn't work. I've put a listener function to detect the new URL and called "webView.load(newURLRequest)". However, the web view never loads the new URL request. I have tried to solve this issue by adding a delay through DispatchQueue. Adding a delay sometimes works and sometimes doesn't. I also tried using NavigationDelegate, but it still didn't help. Below is my code: override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(self.refreshData), name: NSNotification.Name("refreshweb"), object: nil) } @objc func refreshData() { let url = URL (string: "https://www.youtube.com") let requestObj = URLRequest(url: url!) webview.load(requestObj) }
0
0
321
Jul ’24
I am unable to debug a Safari extension in Xcode 16 beta 1 on iOS 18 beta
The process to reproduce: Create a new extension with Xcode 16 beta. Run it on the simulator or any iOS device with iOS 18 beta installed. Open Safari on your Mac, then open Develop -> Device you use. Unable to access these menus for iOS 18: 1. Extension - Extension Background Content 2. Extension - Extension Pop-up Page - popup.html However, for iOS 17.4, I can see these options in Develop -> Device iOS(17.4). I have another extension on the App Store that is not working on the iOS 18 beta, but I am unable to debug it because of this issue.
1
0
541
Jul ’24
Microphone input in website in webview for swiftui
I have a website of a chatbot that also accepts microphone inputs and I embedded that into my swift and the everything other than the mic is working. I have included permission in the info file and here’s some of the code : import SwiftUI import WebKit import AVFoundation struct WebView: UIViewRepresentable { let url: URL class Coordinator: NSObject, WKUIDelegate, WKNavigationDelegate { var parent: WebView init(parent: WebView) { self.parent = parent } func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { decisionHandler(.allow) } func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) { let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in completionHandler() })) parent.presentAlert(alert: alert) } func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) { let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in completionHandler(true) })) alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in completionHandler(false) })) parent.presentAlert(alert: alert) } func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) { let alert = UIAlertController(title: prompt, message: nil, preferredStyle: .alert) alert.addTextField { textField in textField.text = defaultText } alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in completionHandler(alert.textFields?.first?.text) })) alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in completionHandler(nil) })) parent.presentAlert(alert: alert) } func webView(_ webView: WKWebView, requestMediaCapturePermissionFor origin: WKSecurityOrigin, initiatedByFrame frame: WKFrameInfo, type: WKMediaCaptureType, decisionHandler: @escaping (WKPermissionDecision) -> Void) { decisionHandler(.grant) } func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { print("Navigation error: \(error.localizedDescription)") } } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } func makeUIView(context: Context) -> WKWebView { let webConfiguration = WKWebViewConfiguration() webConfiguration.allowsInlineMediaPlayback = true webConfiguration.mediaTypesRequiringUserActionForPlayback = [] let webView = WKWebView(frame: .zero, configuration: webConfiguration) webView.uiDelegate = context.coordinator webView.navigationDelegate = context.coordinator requestMicrophoneAccess() return webView } func updateUIView(_ webView: WKWebView, context: Context) { let request = URLRequest(url: url) webView.load(request) } func requestMicrophoneAccess() { AVAudioSession.sharedInstance().requestRecordPermission { granted in DispatchQueue.main.async { if granted { print("Microphone access granted") } else { print("Microphone access denied") } } } } func presentAlert(alert: UIAlertController) { if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let rootViewController = windowScene.windows.first?.rootViewController { rootViewController.present(alert, animated: true, completion: nil) } } }
0
0
359
Jul ’24
Microphone input in website in webview for swiftui
I have a website of a chatbot that also accepts microphone inputs and I embedded that into my swift and the everything other than the mic is working. I have included permission in the info file and here's some of the code : import SwiftUI import WebKit import AVFoundation struct WebView: UIViewRepresentable { let url: URL class Coordinator: NSObject, WKUIDelegate, WKNavigationDelegate { var parent: WebView init(parent: WebView) { self.parent = parent } func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { decisionHandler(.allow) } func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) { let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in completionHandler() })) parent.presentAlert(alert: alert) } func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) { let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in completionHandler(true) })) alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in completionHandler(false) })) parent.presentAlert(alert: alert) } func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) { let alert = UIAlertController(title: prompt, message: nil, preferredStyle: .alert) alert.addTextField { textField in textField.text = defaultText } alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in completionHandler(alert.textFields?.first?.text) })) alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in completionHandler(nil) })) parent.presentAlert(alert: alert) } func webView(_ webView: WKWebView, requestMediaCapturePermissionFor origin: WKSecurityOrigin, initiatedByFrame frame: WKFrameInfo, type: WKMediaCaptureType, decisionHandler: @escaping (WKPermissionDecision) -> Void) { decisionHandler(.grant) } func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { print("Navigation error: \(error.localizedDescription)") } } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } func makeUIView(context: Context) -> WKWebView { let webConfiguration = WKWebViewConfiguration() webConfiguration.allowsInlineMediaPlayback = true webConfiguration.mediaTypesRequiringUserActionForPlayback = [] let webView = WKWebView(frame: .zero, configuration: webConfiguration) webView.uiDelegate = context.coordinator webView.navigationDelegate = context.coordinator requestMicrophoneAccess() return webView } func updateUIView(_ webView: WKWebView, context: Context) { let request = URLRequest(url: url) webView.load(request) } func requestMicrophoneAccess() { AVAudioSession.sharedInstance().requestRecordPermission { granted in DispatchQueue.main.async { if granted { print("Microphone access granted") } else { print("Microphone access denied") } } } } func presentAlert(alert: UIAlertController) { if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let rootViewController = windowScene.windows.first?.rootViewController { rootViewController.present(alert, animated: true, completion: nil) } } }
0
0
323
Jul ’24
Cannot navigate to external webpages from internal extension pages
In iOS 18, internal extension pages cannot navigate to external webpages, either via href links or through JS methods such as window.location.replace. Nothing happens when you try to navigate to an external webpage. Only other internal pages can be navigated to. This wasn't an issue on previous versions of iOS. It would be appreciated if this can be fixed as soon as possible. Feedback ID: FB14194963
3
1
652
Jul ’24
Undocumented changes in WebKit API in Xcode 16 break apps
Be warned! When developing your app in Xcode 16 be careful!!! The new SDK has changes that cause builds on Xcode Cloud and other non-beta Xcode to have bugs (EVEN WITH IOS TARGET SET LOWER). This wasted 2 days of development time, but in WKNavigationDelegate, the webView(_:decidePolicyFor:decisionHandler:) method has a new type signature that will ONLY work in the latest SDK. The change was that the decisionHandler now has a @MainActor attribute. This causes Swift to recognize that it "almost" meets an optional requirement and suggests that you change it. If you change it, it will cause builds to not include the optional method.
2
0
596
Jul ’24
App Crashes when loading webview " *** Assertion failure in -[UIApplication _performAfterCATransactionCommitsWithLegacyRunloopObserverBasedTiming:block:]"
In my app I am trying to load webview with an URL , I am checking is it loading on main thread also loading webview in main thread using DispatchQueue.main.async { self.loadRequest() } , webview loads successfully, then showing below error app crashes , unable to find the reason. "*** Assertion failure in -[UIApplication _performAfterCATransactionCommitsWithLegacyRunloopObserverBasedTiming:block:]" Thanks in advance
1
0
376
Jul ’24
HTTP requests timing out...
I am new to swift, so any advice would be appreciated. So the I have seen URL and URLSession return a timeout response, the android varient of my app does not show this issue. class HasInternet: ObservableObject { let monitor = NWPathMonitor() let queue = DispatchQueue(label: "Monitor") private var status: NWPath.Status = .requiresConnection @Published var isConnected = false init(){ monitor.pathUpdateHandler = { [weak self] path in if let url = URL(string: "https://google.com") { var request = URLRequest(url: url) request.httpMethod = "HEAD" request.timeoutInterval = 30 let sessionConfig = URLSessionConfiguration.default sessionConfig.timeoutIntervalForRequest = 30.0 sessionConfig.timeoutIntervalForResource = 60.0 URLSession(configuration: sessionConfig) .dataTask(with: request) { (_, response, error) -> Void in guard error == nil else { return } guard (response as? HTTPURLResponse)? .statusCode == 200 else { return } DispatchQueue.main.async { self?.isConnected = true } } .resume() } } monitor.start(queue: queue) } } Here is another place with the same behaviour. func post(dModel: DialogModel? = nil, url: String, type: responseTypes, body: [String: Any], headers: [headerType], async: Bool = true) { //async let semaphore = DispatchSemaphore(value: 0) let timeout: TimeInterval = 10 if let url = URL(string: url) { var request = URLRequest(url: url) request.httpMethod = "POST" request.timeoutInterval = 30 for header in headers { request.setValue(header.value, forHTTPHeaderField: header.key) } do { request.httpBody = try JSONSerialization.data(withJSONObject: body, options: .prettyPrinted) } catch let error { self.processError(dModel: dModel, error: error.localizedDescription, type: .report) return } let sessionConfig = URLSessionConfiguration.default sessionConfig.timeoutIntervalForRequest = 30.0 sessionConfig.timeoutIntervalForResource = 60.0 URLSession(configuration: sessionConfig) .dataTask(with: request) { (data, response, error) -> Void in if let error = error { self.processError(dModel: dModel, error: error.localizedDescription, type: .report) if(async){ semaphore.signal() // Signal semaphore even in case of error } return } if let httpResponse = response as? HTTPURLResponse{ if let unWrappedData = data { if let httpResponseData = String(data: unWrappedData, encoding: .utf8) { self.parse(dModel: dModel, type: type, response: httpResponseData, statusCode: httpResponse.statusCode) } } } else { self.processError(error: "Invalid response") } if(async){ semaphore.signal() // Signal semaphore after processing the response } } .resume() if(async){ semaphore.wait(timeout: .now() + timeout) } } else { processError(error: "Invalid URL") } }
0
0
312
Jul ’24