iOS开发:AppDelegate触发方法时如何打开WebView并关联控制器?
解决AppDelegate中根据服务器响应打开WebView的问题
我来帮你一步步梳理解决方案,结合你的代码给出可直接复用的修改方案:
一、先创建带WebView的专用ViewController
首先需要一个专门用来展示WebView的ViewController,方便后续管理和复用,比如命名为WebViewController:
import UIKit import WebKit class WebViewController: UIViewController { private var webView: WKWebView! var targetURL: URL? // 用于接收要加载的目标URL override func viewDidLoad() { super.viewDidLoad() setupWebView() loadTargetURL() } private func setupWebView() { webView = WKWebView(frame: view.bounds) webView.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.addSubview(webView) } private func loadTargetURL() { guard let url = targetURL else { return } let request = URLRequest(url: url) webView.load(request) } }
二、在AppDelegate中正确引用并展示WebViewController
网络请求是异步操作,所以所有UI相关的代码必须回到主线程执行,同时要避免循环引用和强制解包带来的崩溃风险,以下是修正后的完整代码:
import UIKit import Alamofire import WebKit @main class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { let handled = ApplicationDelegate.shared.application(app, open: url, options: options) // 将Codable结构体移到方法外,避免重复定义 struct JsonResponse: Codable { let ads_enabled: Bool } print(url) // 修复URL的多余括号问题 Alamofire.request("https://appgootop.com").responseJSON { [weak self] response in guard let self = self else { return } switch response.result { case .success: guard let data = response.data else { print("未获取到响应数据") return } do { let product = try JSONDecoder().decode(JsonResponse.self, from: data) print(product.ads_enabled) // 回到主线程处理UI操作 DispatchQueue.main.async { if !product.ads_enabled { // 按你的逻辑:ads_enabled为false时打开WebView guard let webURL = URL(string: "https://google.com") else { return } // 补全HTTPS协议头,否则WebView无法加载 // 创建WebViewController实例并传递URL let webVC = WebViewController() webVC.targetURL = webURL // 获取当前根控制器并展示WebView if let rootVC = self.window?.rootViewController { // 如果根控制器是导航控制器,用push;否则用present if let navVC = rootVC as? UINavigationController { navVC.pushViewController(webVC, animated: true) } else { rootVC.present(webVC, animated: true) } } } } } catch { print("JSON解析失败:\(error.localizedDescription)") } case .failure(let error): print("网络请求失败:\(error.localizedDescription)") } } return handled } // 其他AppDelegate生命周期方法... }
关键细节说明
- 避免方法内定义结构体:把
JsonResponse移到方法外,避免每次调用方法重复定义造成资源浪费。 - 异步操作必须回到主线程:网络回调在后台线程执行,所有UI更新代码一定要用
DispatchQueue.main.async包裹,否则会触发崩溃。 - 补全URL协议头:原代码中的
google.com缺少HTTPS协议,WebView无法正常加载,必须写成完整的https://google.com。 - 替换强制解包
try!:用do-catch处理JSON解析错误,避免因数据格式异常导致崩溃。 - 弱引用
self:在网络回调中使用[weak self]避免循环引用,防止内存泄漏。
内容的提问来源于stack exchange,提问作者Cap Jeff
相关产品推荐
相关产品推荐

