Description
Capacitor Version
💊 Capacitor Doctor 💊
Latest Dependencies:
@capacitor/cli: 7.0.1
@capacitor/core: 7.0.1
@capacitor/android: 7.0.1
@capacitor/ios: 7.0.1
Installed Dependencies:
@capacitor/android: not installed
@capacitor/cli: 7.0.1
@capacitor/core: 7.0.1
@capacitor/ios: 7.0.1
[success] iOS looking great! 👌
Other API Details
➜ mobile git:(cap) ✗ npm --version
11.0.0
➜ mobile git:(cap) ✗ node --version
v23.6.0
➜ mobile git:(cap) ✗ pod --version
1.16.2
➜ mobile git:(cap) ✗ go version
go version go1.23.4 darwin/arm64
Platforms Affected
- iOS
- Android
- Web
Current Behavior
I have custom native code to add a gomobile static lib as a framework. When I switched to use my bundled site in public
for prod, it failed with:
⚡️ WebView failed provisional navigation
⚡️ Error: The file “public” couldn’t be opened.
This happens in both simulator and physical iPhone (both iOS 18.2).
This error returns exactly one search result: #6974 . It's closed, but nevertheless:
- It's suggested there's a workaround, but not how? I share mine below.
- The Go team blames Apple (Foundation Framework) and proceeds to stick head into sand
- Tim Apple isn't even informed, afaik
- In development with HMR, I didn't notice this because if there's a
serverUrl
it's not triggered
The gomobile command used was: gomobile bind -ldflags="-s" -target ios -tags ios -o ./ios/App/Pld.xcframework
Expected Behavior
Webview should load normally & peacefully.
Project Reproduction
it's not easy to do atm...
Additional Information
I managed to find a workaround through MyViewController
(see docs for how to set it up). The actual fix is a one-liner, but to set it up is quite tedious, especially if you're not already using a custom view controller.
import UIKit
import Capacitor
public struct CustomRouter: Router {
public init() {}
public var basePath: String = ""
public func route(for path: String) -> String {
// FIX: Never pass an empty string here
let pathUrl = URL(fileURLWithPath: path.isEmpty ? "/" : path)
// If there's no path extension it also means the path is empty or a SPA route
if pathUrl.pathExtension.isEmpty {
return basePath + "/index.html"
}
return basePath + path
}
}
class MyViewController: CAPBridgeViewController {
// CRITICAL: Must pass our own router otherwise *no bueno*
override open func router() -> any Router {
CustomRouter()
}
override open func capacitorDidLoad() {
// Here I register my plugin, but the failure occurs even if I don't register it.
bridge?.registerPluginInstance(PldPlugin())
}
}
My understanding is that the non-deterministic behavior of URL(fileURLWithPath:)
occurs when the path is empty. Normally an empty path translates to file:///
which is equivalent to passing /
.
God knows what combination of things causes this to happen, but if Capacitor can avoid this non-determinism perhaps that's an improvement? It certainly is for me (and clearly, whoever posted that other issue). Happy to send a PR if so.
(Obligatory thanks for a great framework. I'm new to mobile dev and I can't thank the contributors enough.)