Автоматическое перенаправление веб-приложения на начальную страницу проблемы iOS (оно НЕ должно перенаправляться) - PullRequest
6 голосов
/ 07 октября 2019

У меня есть веб-приложение для Android и iOS, которое открывает веб-страницу. Приложение отлично работает для Android и большинства iOS-устройств.

Но по некоторым причинам, для некоторых пользователей iOS, приложение случайным образом перенаправляет пользователей на начальную страницу через несколько минут, используя приложение.

Пользователь открывает приложение на начальной странице, нажимает кнопкупо ссылке на другую страницу пользователь читает страницу, а затем по какой-то причине приложение перенаправляет обратно на начальную страницу.

Нет кода JavaScript, который выполняет перенаправление в приложении, есть работник службы,но без перенаправлений.

Это происходит не всегда, но происходит и раздражает пользователей.

Есть идеи о том, что может происходить?

Обновление: фрагмент кода

ViewController.swift

import UIKit
import WebKit
import Firebase
import UserNotifications
class ViewController: UIViewController , WKNavigationDelegate, WKUIDelegate{

    @IBOutlet weak var loading: UIActivityIndicatorView!
    @IBOutlet weak var screenSplash: UIImageView!
    @IBOutlet weak var webView: WKWebView!
    let reachability = Reachability()!

    var request = URLRequest(url: URL(string: "https://app.com/webview")!)

    var screen = CGRect.zero

    var flag = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        screen = UIScreen.main.bounds
        webView.frame.origin.x = 0
        webView.frame.origin.y = 0
        webView.frame.size.height = screen.height
        webView.frame.size.width = screen.width

        webView?.navigationDelegate = self

        webView.scrollView.bounces = false
        webView.isOpaque = false
        webView.backgroundColor = UIColor.clear
        webView?.load(request)
        self.view.addSubview(webView)

        screen = UIScreen.main.bounds
        webView.frame.origin.x = 0
        webView.frame.origin.y = 0
        webView.frame.size.height = screen.height
        webView.frame.size.width = screen.width


        webView.navigationDelegate = self
        self.webView?.uiDelegate = self
        view.addSubview(webView!)
    }


    @objc func internetChanged(note: Notification){
        let reachability = note.object as! Reachability
        if reachability.connection != .none{
            print("Volvio la conexion")
            webView?.load(request)
            viewDidLoad()

        }else{
            //let alert = UIAlertController(title: "", message: "Es necesario tener una conexión activa a internet", preferredStyle: .alert)
            //alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            //self.present(alert, animated: true, completion: nil)
            print("Es necesario tener una conexión activa a internet")

            let htmlPath = Bundle.main.path(forResource: "error", ofType: "html")
            let folderPath = Bundle.main.bundlePath
            let baseUrl = URL(fileURLWithPath: folderPath, isDirectory: true)
            do{

                let htmlString = try NSString(contentsOfFile:htmlPath!, encoding:String.Encoding.utf8.rawValue)
                self.webView.loadHTMLString(htmlString as String,baseURL:  baseUrl)
            }catch{

            }
        }
    }


    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!)
    {

    }
    func webView(webView: WKWebView!, createWebViewWithConfiguration configuration: WKWebViewConfiguration!, forNavigationAction navigationAction: WKNavigationAction!, windowFeatures: WKWindowFeatures!) -> WKWebView! {
        if navigationAction.targetFrame == nil {
            webView.load(navigationAction.request)
        }
        return nil
    }


    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)
    {

        let fmcToken=InstanceID.instanceID().token() as! String
       print(fmcToken)
        webView.evaluateJavaScript("(function() { if(typeof sendDeviceToken === 'function'){  return sendDeviceToken('ios','\(fmcToken)');  }else{ return false; }  })()", completionHandler: { (data, error) in
            if let err = error {
                print(err)
                print(err.localizedDescription)
            } else {
                guard let dataValue = data else {return}
                print("res sendDeviceToken")
                print(dataValue)
            }
        })

        screenSplash.isHidden = true
        loading.isHidden = true
        webView.evaluateJavaScript("document.getElementsByTagName('meta')['viewport'].content='initial-scale=1.0, user-scalable=no';"){
            (result,error) in if error != nil  {
                print(result ?? "")
            }
        }

        if(flag==0){
            NotificationCenter.default.addObserver(self, selector: #selector(internetChanged), name: Notification.Name.reachabilityChanged, object: reachability)
            do{
                try reachability.startNotifier()

            }catch{
                print("No se pudo iniciar la notificacion")
            }
            flag=flag+1
        }
    }

    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        if navigationAction.navigationType == .linkActivated  {
            if let url = navigationAction.request.url,
                let host = url.host, !host.hasPrefix("app.com")  || url.absoluteString.contains("/share/"),
                UIApplication.shared.canOpenURL(url) {
                UIApplication.shared.open(url)
                print(url)
                print("Redirected to browser. No need to open it locally")
                decisionHandler(.cancel)
            } else {
                // print("Open it locally")
                decisionHandler(.allow)
            }
        } else {
            // print("not a user click")
            decisionHandler(.allow)
        }
    }


    //fix the alert
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {

        let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)

        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
            completionHandler()
        }))

        self.present(alertController, animated: true, completion: nil)
    }
    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {

        let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)

        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
            completionHandler(true)
        }))

        alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
            completionHandler(false)
        }))

        self.present(alertController, animated: true, completion: nil)
    }

    func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {

        let alertController = UIAlertController(title: nil, message: prompt, preferredStyle: .actionSheet)

        alertController.addTextField { (textField) in
            textField.text = defaultText
        }

        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
            if let text = alertController.textFields?.first?.text {
                completionHandler(text)
            } else {
                completionHandler(defaultText)
            }

        }))

        alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in

            completionHandler(nil)

        }))

        self.present(alertController, animated: true, completion: nil)
    }
    //end fix the alert

    func clickActionOpen(action: String) {
        request = URLRequest(url: URL(string: "https://app.com/webview?click_action="+action)!)

       var requestClick = URLRequest(url: URL(string: "https://app.com/webview?click_action="+action)!)
        webView.load(requestClick)
    }
}
Работник службы
// Incrementing CACHE_VERSION will kick off the install event and force previously cached
// resources to be cached again.
// https://github.com/GoogleChrome/samples/blob/gh-pages/service-worker/custom-offline-page/service-worker.js
var CACHE_VERSION = 'v4'
var CACHE_NAME = CACHE_VERSION + ':sw-cache-'

function onInstall(event) {
  console.log('[Serviceworker]', 'Installing!', event)
  event.waitUntil(
    caches.open(CACHE_NAME).then(function prefill(cache) {
      return cache.addAll([
        '<%= asset_path "admin.js" %>',
        '<%= asset_path "admin.css" %>',
        '<%= asset_path "site/homepage-logo.png" %>'
      ])
    })
  )
}

function onActivate(event) {
  console.log('[Serviceworker]', 'Activating!', event)
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames
          .filter(function(cacheName) {
            // Return true if you want to remove this cache,
            // but remember that caches are shared across
            // the whole origin
            return cacheName.indexOf(CACHE_VERSION) !== 0
          })
          .map(function(cacheName) {
            return caches.delete(cacheName)
          })
      )
    })
  )
}

// Borrowed from https://github.com/TalAter/UpUp
// then from https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/onfetch
function onFetch(event) {
  event.respondWith(
    caches.match(event.request).then(function(response) {
      if (response) {
        // console.log('Found response in cache:', response)

        return response
      }
      // console.log('No response found in cache. About to fetch from network...')

      return fetch(event.request).then(function(response) {
        // console.log('Response from network is:', response)

        return response
      }).catch(function(error) {
        // console.error('Fetching failed:', error)

        throw error
      })
    })
  )
}

self.addEventListener('install', onInstall)
self.addEventListener('activate', onActivate)
self.addEventListener('fetch', onFetch)

Ответы [ 2 ]

6 голосов
/ 26 октября 2019

Из сценария, который вы объяснили, страница может быть перезагружена, если метод internetChanged вызывается в неожиданном сценарии.

Я вижу, что сценарий происходит, если состояние сети устройства изменяетсяв то время как viewController отображается. Вы наблюдали уведомление в методе func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!). поэтому при изменении состояния сети будет вызван метод internetChanged. И в if, и в else метода есть логика для загрузки веб-представления.

Также я вижу, что вы наблюдали уведомление, но никогда не удаляли наблюдателя. Таким образом, ViewController будет иметь утечки памяти и не может быть освобожден из памяти. Я бы посоветовал вам удалить наблюдателя в deinit

Еще одна вещь, вы можете лучше наблюдать уведомление в -viewDidLoad вместо didFinish метода. Теперь, что происходит в соответствии с текущей логикой, всякий раз, когда веб-представление перезагружается, новый наблюдатель добавляется в ViewController в методе func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!). Итак, давайте возьмем как-то метод internetChanged, который вызывается 3 раза, после чего будут добавлены 3 наблюдателя. Поэтому в следующий раз, когда сеть изменится, она будет internetChanged трижды вызываться, что приведет к загрузке веб-страницы 3 раза один за другим, и цикл продолжится.

0 голосов
/ 16 октября 2019

Причина может быть

  • ISP (провайдер интернет-услуг)
  • для ruby-on-rails, аутентификации и использования их authentication_token для проверки сетевых запросов пользователей к вашему API. если нет, приложение будет остановлено.

Надеюсь, это поможет вам.

...