Back to all

iOS Universal Links open app but URL is dropped: SceneDelegate fix

Hello Median team, our released Horse103 iOS app opens when an article link is tapped, but it does not navigate to the linked article. Please investigate the native scene handoff and include a correction in App Studio cloud builds.
App: Horse103 / 賽馬103. Bundle ID: co.median.ios.wexabbq. Released version: 1.0.3 (18). GoNativeCore: 3.0.14. Example link: https://horse103.com/horse103/articles/f9ma-drift-reminder/100
The released IPA uses UIApplicationSceneManifest with Median.SceneDelegate. Its implemented Objective-C methods are only window, setWindow:, scene:willConnectToSession:options:, init and .cxx_destruct. It does not implement scene:continueUserActivity: or scene:openURLContexts:. Optional protocol metadata is present, but these handlers are not implemented by the class.
A fresh iOS source export (engine revision aad2314fdcbabdfbd4c7e58eb98c6f9a617e6b8c) confirms that SceneDelegate.swift creates a window but ignores connectionOptions and has no warm URL callbacks. Existing URL handling remains in LEANAppDelegate. The article URL itself returns without redirection for the native user agent, and the canonical association file and Apple CDN copy match.
Proposed one-file replacement for LeanIOS/SceneDelegate.swift is below. It applies the existing Median launch-deeplink normalizer before root-view creation, forwards warm Universal Links and URL contexts to the existing AppDelegate handlers, and forwards scene lifecycle events to retain the existing Median bridge behavior. It retains existing domains, URL schemes, entitlements and URL validation.
Validation: a Swift harness executing the actual SceneDelegate with small UIKit/Median boundary doubles fails 10 of 13 assertions against the exported original and passes all 13 against the replacement. Assertions cover cold/warm Universal Links, cold/warm custom schemes, exact article/query/fragment preservation, no duplicate cold delivery, ordinary homepage launch, URL context options and lifecycle forwarding. The replacement also passed type checking against the real iOS 26.5 SDK and GoNativeCore 3.0.14 headers. These checks do not establish full-app or physical-device acceptance.
Please review and integrate this or an equivalent upstream fix, confirm which engine/build contains it, and validate both cold and warm entry using the exact article URL above. We need a corrected build through the existing App Studio signing and App Store Connect workflow. An ordinary rebuild of the same uncorrected engine will retain the defect.
No credentials, private signing material or account configuration are included.
Proposed SceneDelegate.swift
// Horse103 adapter for Median iOS engine aad2314 / GoNativeCore 3.0.14.
// Keep the existing AppDelegate and Median URL validation/navigation handlers.
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?

func scene(
_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions
) {
guard let windowScene = scene as? UIWindowScene else { return }

// Scene-based launches deliver their URL here, not in AppDelegate's
// launchOptions. Set Median's initial URL before the storyboard loads.
let launchActivity = connectionOptions.userActivities.first {
$0.activityType == NSUserActivityTypeBrowsingWeb && $0.webpageURL != nil
}
let launchContext = connectionOptions.urlContexts.first
let launchURL = launchActivity?.webpageURL ?? launchContext?.url
let preparedLaunch = launchURL.map {
GoNativeAppConfig.shared().applyLaunchDeeplink($0)
} ?? false

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let rootVC = storyboard.instantiateInitialViewController()
let window = UIWindow(windowScene: windowScene)
window.rootViewController = rootVC
self.window = window
if let appDelegate = UIApplication.shared.delegate as? NSObject {
appDelegate.setValue(window, forKey: "window")
}
window.makeKeyAndVisible()

// Non-navigation callbacks must still reach existing bridge handlers.
// A prepared article URL has already become the first page: no replay.
if !preparedLaunch {
if let launchActivity {
self.scene(scene, continue: launchActivity)
} else if let launchContext {
self.scene(scene, openURLContexts: [launchContext])
}
}
}

func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
let application = UIApplication.shared
_ = application.delegate?.application?(
application, continue: userActivity, restorationHandler: { _ in }
)
}

func scene(_ scene: UIScene, openURLContexts URLContexts: Set

// UIKit also moves these notifications to the scene delegate. Forward them
// so Median's existing bridge resume/background behavior continues to run.
func sceneDidBecomeActive(_ scene: UIScene) {
UIApplication.shared.delegate?.applicationDidBecomeActive?(UIApplication.shared)
}

func sceneWillResignActive(_ scene: UIScene) {
UIApplication.shared.delegate?.applicationWillResignActive?(UIApplication.shared)
}

func sceneWillEnterForeground(_ scene: UIScene) {
UIApplication.shared.delegate?.applicationWillEnterForeground?(UIApplication.shared)
}

func sceneDidEnterBackground(_ scene: UIScene) {
UIApplication.shared.delegate?.applicationDidEnterBackground?(UIApplication.shared)
}
}