I’ve made a sport utilizing internet applied sciences, and for the iOS model I’m utilizing a webview to show it to customers.
Whereas it’s working, I might prefer to intercept requests to exterior belongings and serve bundled belongings as a substitute for efficiency causes.
Probably the most simple implementation for me appeared to be utilizing a WKWebView
and setting a customized url scheme handler utilizing setURLSchemeHandler
on the WKWebViewConfiguration
. For some purpose, I couldn’t get https
to work because the second argument of setURLSchemeHandler
(forURLScheme). I ‘hacked’ my means by means of and got here up with the next code which doesn’t appear to crash however isn’t working correctly both.
App.swift
import SwiftUI
@major
struct App: App {
var physique: some Scene {
WindowGroup {
ContentView()
}
}
}
ContentView.swift
import SwiftUI
import WebKit
struct ContentView: View {
// Exterior = random prefix since https will not be working
@State non-public var urlString = "exterior://instance.com/"
var physique: some View {
WebView(urlString: $urlString)
.edgesIgnoringSafeArea(.all)
}
}
struct WebView: UIViewRepresentable {
@Binding var urlString: String
func makeUIView(context: Context) -> WKWebView {
let webConfiguration = WKWebViewConfiguration()
webConfiguration.preferences.isElementFullscreenEnabled = true
let schemeHandler = CustomURLSchemeHandler()
// exterior = random string since https will not be working
webConfiguration.setURLSchemeHandler(schemeHandler, forURLScheme: "exterior")
return WKWebView(body: .zero, configuration: webConfiguration)
}
// Load the URL when the view seems or the URL modifications
func updateUIView(_ uiView: WKWebView, context: Context) {
if let url = URL(string: urlString) {
let request = URLRequest(url: url)
uiView.load(request)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
CustomUrlSchemeHandler.swift
import WebKit
class CustomURLSchemeHandler: NSObject, WKURLSchemeHandler {
let assets: [[String: String]] = [
["path": "dist/audio/ambient/action_2.mp3", "mime_type": "audio/mpeg"],
["path": "dist/fonts/Fontin-Bold.ttf", "mime_type": "font/ttf"],
["path": "dist/img/backgrounds/2_titlescreen_921x1.webp", "mime_type": "image/webp"]
]
func webView(_ webView: WKWebView, begin urlSchemeTask: WKURLSchemeTask) {
guard let url = urlSchemeTask.request.url else {
urlSchemeTask.didFailWithError(NSError(area: "CustomURLSchemeHandler", code: 0, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"]))
return
}
// Take away the "exterior://" prefix
let httpsURLString = url.absoluteString.replacingOccurrences(of: "exterior://", with: "https://")
// Iterate by means of assets to discover a matching path
for useful resource in assets {
if let path = useful resource["path"], url.absoluteString == "https://instance.com/" + path {
// Serve the native useful resource
if let localFilePath = Bundle.major.path(forResource: (path as NSString).lastPathComponent, ofType: nil),
let localFileData = attempt? Knowledge(contentsOf: URL(fileURLWithPath: localFilePath)) {
let response = URLResponse(url: url, mimeType: mimeType, expectedContentLength: localFileData.depend, textEncodingName: nil)
urlSchemeTask.didReceive(response)
urlSchemeTask.didReceive(localFileData)
urlSchemeTask.didFinish()
return
}
}
}
// no match, load the info from httpsURLString
if let httpsURL = URL(string: httpsURLString) {
let session = URLSession.shared
let activity = session.dataTask(with: httpsURL) { (information, response, error) in
if let error = error {
print(error)
urlSchemeTask.didFailWithError(error)
} else if let information = information, let response = response {
let mimeType = response.mimeType ?? "utility/octet-stream"
let urlResponse = URLResponse(url: httpsURL, mimeType: mimeType, expectedContentLength: information.depend, textEncodingName: nil)
// Ship the response and information again to urlSchemeTask
urlSchemeTask.didReceive(urlResponse)
urlSchemeTask.didReceive(information)
urlSchemeTask.didFinish()
}
}
activity.resume()
} else {
urlSchemeTask.didFailWithError(NSError(area: "CustomURLSchemeHandler", code: 0, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"]))
}
}
func webView(_ webView: WKWebView, cease urlSchemeTask: WKURLSchemeTask) {
// Deal with the cancellation of the URL scheme activity if obligatory
}
}
I have never even been in a position to check if serving native belongings even work, as a result of even when there a no matches discovered with the code above, the response is actually sluggish and it appears to interrupt sure stuff (by the appears to be like of it, CSS information?).
I really feel like I’ve tried all choices on the market however I really feel like I am utterly caught. To make issues worse, my server is beginning to battle due to all of the folks continuously retrieving all of the picture and audio belongings that make up my sport.
Does anybody know the right way to intercept all requests to exterior belongings and serve bundled belongings as a substitute (in the event that they exist)?
Thanks prematurely.