从 AppDelegate 更改 WebView url

Posted

技术标签:

【中文标题】从 AppDelegate 更改 WebView url【英文标题】:Change WebView url from AppDelegate 【发布时间】:2017-04-14 09:07:50 【问题描述】:

我在 AppDelegate 类中接收来自 Firebase 的通知。 此通知包含一个名为“notif_url”的字符串。我已将此值放入名为“desired_url”的变量中,现在我需要使用“desired_url”值更改我的 WebView url。

但我无法访问 webview 来更改它的 url,如下所示:

@IBOutlet weak var my_web_view: UIWebView!

func load_url(server_url: String)
    let url = URL(string: server_url);
    let request = URLRequest(url: url!);
    my_web_view.loadRequest(request);


load_url(server_url: desired_url);

你知道我是否可以这样做,如果可以,怎么做? 图片:

编辑 1: 加上breakPoint后知道错了行,好像不是这一行:

my_web_view.loadRequest(request)

编辑 2: 如果需要,这是我的 AppDelegate 类代码的一部分。

import UIKit
import UserNotifications

import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate 

    var window: UIWindow?
    let gcmMessageIDKey = "gcm.message_id"
    @IBOutlet weak var my_web_view: UIWebView!

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 
        return true
    


// [START ios_10_message_handling]
@available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate

    // Receive displayed notifications for iOS 10 devices.
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
        print("Step : 12");
        let userInfo = notification.request.content.userInfo
        // Print message ID.
        if let messageID = userInfo[gcmMessageIDKey]
            print("Message ID: \(messageID)")
        

        // Print full message.
        print(userInfo)
        var url: String = userInfo[AnyHashable("url")] as! String;
        load_url(server_url: url);

        // Change this to your preferred presentation option
        completionHandler([])
    

    func load_url(server_url: String)
        /*
        let url = URL(string: server_url);
        let request = URLRequest(url: url!);
        my_web_view.loadRequest(request);
         */

        guard let url = URL(string: server_url) else 
            print("Invalid URL")
            return
        

        print("TRY : "+server_url);

        let request = URLRequest(url: url)
        my_web_view.loadRequest(request)
    

编辑 3: 如果需要,那是我的 ViewController 类代码。

import Foundation
import UIKit
import SafariServices
import UserNotifications

class ViewController: UIViewController, UIWebViewDelegate

    @IBOutlet weak var my_web_view: UIWebView!
    @IBOutlet weak var my_loading_view: UIView!
    @IBOutlet weak var spinner : UIActivityIndicatorView!
    @IBOutlet weak var app_logo : UIImageView!

    @IBOutlet weak var deadlinePicker: UIDatePicker!
    @IBOutlet weak var titleField: UITextField!

    var new_url: String = "";

    override func viewDidLoad()
        super.viewDidLoad()

        let server_url = "https://www.sortirauhavre.com/";

        NotificationCenter.default.addObserver(self, selector: #selector(self.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
        rotated();

        spinner.startAnimating();


        my_web_view.scrollView.bounces = false;
        my_web_view.scrollView.isScrollEnabled = true;

        let url = URL(string: server_url);
        let request = URLRequest(url: url!);
        my_web_view.loadRequest(request);
    

    // CETTE FONCITON SE LANCE A LA ROTATION DE L'APPAREIL
    func rotated()
        app_logo.center = my_loading_view.center;
        let y = app_logo.frame.origin.y;
        let h = app_logo.frame.size.height
        app_logo.frame.origin.y = y-(h/2);

        spinner.center = my_loading_view.center;
    

    // CETTE FONCTION MET EN ARRIERE PLAN L'ANNIMATION DE CHARGEMENT
    func removeLoader()
        self.view.addSubview(my_web_view);
    

    // CETTE FONCTION MET EN PREMIER PLAN L'ANNIMATION DE CHARGEMENT
    func addLoader()
        self.view.addSubview(my_loading_view);
    

    // CETTE FONCTION SE DECLANCHE QUAND LES PAGES DE LA WEBVIEW COMMENCE A CHANGER
    func webViewDidStartLoad(_ webView: UIWebView)
        addLoader();
        let server_url = "https://www.sortirauhavre.com/";
        _ = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.removeLoader), userInfo: nil, repeats: false);
        if let text = webView.request?.url?.absoluteString
            if text.hasPrefix(server_url)
            
            else if text != ""
                UIApplication.shared.openURL(URL(string: text)!)
                my_web_view.goBack()
            
        
    

    // CETTE FONCTION SE DECLANCHE QUAND LES PAGES DE LA WEBVIEW FINI DE CHANGER
    func webViewDidFinishLoad(_ webView: UIWebView)
        let server_url = "https://www.sortirauhavre.com/";
        _ = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.removeLoader), userInfo: nil, repeats: false);
        if let text = webView.request?.url?.absoluteString
            if text.hasPrefix(server_url)
            
            else if text != ""
                UIApplication.shared.openURL(URL(string: text)!)
                my_web_view.goBack()
            
        
    

【问题讨论】:

“来自 AppDelegate”是什么意思?如果您只是在应用程序委托中创建一个新实例,@IBOutlets 将不会加载。 我的“AppDelegate”类中有一个函数。这个函数接收一个通知 -> 一个字符串(一个 url)。我需要的是从此函数更改 Webview url。 我明白了,但我的意思是您如何从您的应用代理访问 Web 视图?如果您将整个功能添加到您的问题中,那可能是最好的。 如果我理解,我无法从此类更改 WebView url,我必须在 ViewController 类中创建事件来处理 nbotification 并使其工作:/ 不,很可能从应用代理更改 Web 视图 URL,只要您能发布到目前为止所做的事情,我就能为您提供帮助。 【参考方案1】:

您正在强制解包 url,这不是一个有效的 URL。我建议添加 guard 语句以防止在创建无效 URL 时崩溃:

func load_url(server_url: String) 
    guard let url = URL(string: server_url) else 
        print("Invalid URL")
        return
    

    let request = URLRequest(url: url)
    my_web_view.loadRequest(request)

当您在 AppDelegate 中获取 URL 时,您不能简单地从此类更新 UIWebView。您需要调用my_web_view 的父类中的一个函数来更新URL

// App Delegate

var serverURL: String?

func load_url(server_url: String) 
    serverURL = server_url
    let notificationName = Notification.Name("updateWebView")
    NotificationCenter.default.post(name: notificationName, object: nil)



// View Controller

override func viewDidLoad() 
    let notificationName = Notification.Name("updateWebView")
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.updateWebView), name: notificationName, object: nil)

    updateWebView()


func updateWebView() 
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let serverURL = appDelegate.serverURL

    guard let url = URL(string: serverURL) else 
        print("Invalid URL")
        return
    

    let request = URLRequest(url: URL)
    my_web_view.loadRequest(request)

【讨论】:

感谢您的帮助,打印的 url 值(字符串)返回给我:“https://www.sortirauhavre.com/a-la-une/24-heures-kino/”我认为这是一个很好的网址不? (在 url 中添加空格会导致堆栈隐藏 url 的前缀) 有什么问题? 您是否确保已正确连接故事板中的 my_web_view?在函数的开头放置一个断点并确定应用程序崩溃的行。 这里好像崩溃了 "let url = URL(string: server_url);" @TomSkat 查看我的编辑。您现在可以检查 URL 是否有效。我可以使用您提供的地址确认上述代码对我有效【参考方案2】:

您无需创建视图控制器的新实例或尝试复制插座,只需访问视图控制器的当前实例即可。您可以使用:

    视图控制器的全局值,或 类似单例的模式。

然后您可以通过调用myGlobalViewController.webViewViewController.instance.webView 从您的应用委托访问该实例。

所以,这里有一个例子:

import UIKit

private var thisViewController: ViewController? // Will hold the instance.

class ViewController: UIViewController 

    static var instance: ViewController 
        guard let thisViewController = thisViewController else  fatalError()  // Don't do this unless you're 100% sure that you'll never access this before the instance is loaded.
        return thisViewController
    

    @IBOutlet weak var webView: UIWebView!

    override func viewDidLoad() 
        super.viewDidLoad()
        thisViewController = self // Set the property to self.
    
...

在此之后,您可以从您的应用代理访问 Web 视图:

func load_url(server_url: String)
    guard let url = URL(string: server_url) else 
        return
    

    let request = URLRequest(url: url)
    ViewController.instance.webView.loadRequest(request)

【讨论】:

非常感谢 xoudini,我没有测试你的例子,因为亚历山大的例子做得很好。但这很重要:D

以上是关于从 AppDelegate 更改 WebView url的主要内容,如果未能解决你的问题,请参考以下文章

AppDelegate.m 需要将数据发送到单独的 ViewController 的 WebView

如何从 AppDelegate 更改 UINavigationBar 背景颜色

如何在AppDelegate获取位置,并将lat和long传递给另一个VC并加载webview

可以在运行时更改 AppDelegate

异步请求后从 AppDelegate 更改初始视图控制器

快速从另一个视图控制器更改 webview 的 url