From d4ae8f427fc546e4907f5aa102fb9fcc3636c903 Mon Sep 17 00:00:00 2001 From: Zhou Weidong <502333560@qq.com> Date: Mon, 26 Oct 2026 09:35:29 +0800 Subject: [PATCH] =?UTF-8?q?fix(ios):=20=E7=94=A8=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E7=BD=91=E7=BB=9C=E8=AF=B7=E6=B1=82=E5=94=A4=E8=B5=B7=E6=97=A0?= =?UTF-8?q?=E7=BA=BF=E6=95=B0=E6=8D=AE=E9=80=89=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flutter 的接口请求不会触发系统选择框,进入前台后补一次 URLSession 请求。 --- ios/Runner/AppDelegate.swift | 9 +++++++++ ios/Runner/SceneDelegate.swift | 7 ++++++- ios/Runner/WirelessDataPrompt.swift | 20 +++++++++++++++++--- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 88ec5d6..b33feff 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -51,6 +51,15 @@ final class RunnerFlutterViewController: FlutterViewController { return super.application(application, didFinishLaunchingWithOptions: launchOptions) } + override func applicationDidBecomeActive(_ application: UIApplication) { + super.applicationDidBecomeActive(application) + requestWirelessDataPrompt() + } + + func requestWirelessDataPrompt() { + wirelessDataPrompt.requestSystemPrompt() + } + func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) registerWirelessDataChannel(engineBridge) diff --git a/ios/Runner/SceneDelegate.swift b/ios/Runner/SceneDelegate.swift index b9ce8ea..c1a5618 100644 --- a/ios/Runner/SceneDelegate.swift +++ b/ios/Runner/SceneDelegate.swift @@ -1,6 +1,11 @@ +// Author: fruit.com.cn + import Flutter import UIKit class SceneDelegate: FlutterSceneDelegate { - + override func sceneDidBecomeActive(_ scene: UIScene) { + super.sceneDidBecomeActive(scene) + (UIApplication.shared.delegate as? AppDelegate)?.requestWirelessDataPrompt() + } } diff --git a/ios/Runner/WirelessDataPrompt.swift b/ios/Runner/WirelessDataPrompt.swift index 63e3610..04b50bf 100644 --- a/ios/Runner/WirelessDataPrompt.swift +++ b/ios/Runner/WirelessDataPrompt.swift @@ -4,15 +4,19 @@ import CoreTelephony import Flutter import Foundation -/// 监听系统无线数据选择,供 Flutter 在首个接口请求前等待。 +/// 监听系统无线数据选择,并用 URLSession 唤起系统选择框。 final class WirelessDataPrompt { static let channelName = "com.stormg.lumadrama/wireless-data" static let awaitDecisionMethod = "awaitDecision" + /// 系统选择框由 URLSession 触发,Dart 的 Socket 请求不会弹出。 + private static let promptURL = URL(string: "https://captive.apple.com/hotspot-detect.html") + private let cellularData = CTCellularData() private let lock = NSLock() private var pending: [FlutterResult] = [] private var decided = false + private var didRequestPrompt = false init() { cellularData.cellularDataRestrictionDidUpdateNotifier = { [weak self] state in @@ -22,7 +26,17 @@ final class WirelessDataPrompt { } } - /// 状态未选择时先挂起;用户点选后完成全部等待。 + /// 应用进入前台后请求一次,促使系统弹出无线数据选择。 + func requestSystemPrompt() { + guard !didRequestPrompt, let promptURL = Self.promptURL else { + return + } + didRequestPrompt = true + _ = cellularData.restrictedState + URLSession.shared.dataTask(with: promptURL) { _, _, _ in }.resume() + } + + /// 未允许前先挂起;用户允许无线数据后再放行。 func awaitDecision(_ result: @escaping FlutterResult) { lock.lock() if decided { @@ -37,7 +51,7 @@ final class WirelessDataPrompt { } private func completeIfDecided(_ state: CTCellularDataRestrictedState) { - if state == .restrictedStateUnknown { + if state != .notRestricted { return } lock.lock()