You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:46:09