Angular.js: Intisari tak terbatas tentang perubahan lokasi di iOS 9 dengan UIWebView (bukan di Safari/ wkWebView)

Dibuat pada 30 Jun 2015  ·  154Komentar  ·  Sumber: angular/angular.js

HTML sederhana berikut menunjukkan masalahnya:

<!DOCTYPE html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular-route.js"></script>
        <script>
            angular.module('fail', ['ngRoute'])
            .config(function($routeProvider) {
                $routeProvider
                .when('/a', {
                    template: '<a ng-href="#/b">a</a>'
                })
                .when('/b', {
                    template: '<a ng-href="#/a">b</a>'
                })
                .otherwise({
                    redirectTo: '/a'
                });
            });
        </script>
    </head>
    <body ng-app="fail">
        <div ng-view></div>
    </body>
</html>

Ini berjalan seperti yang diharapkan pada sebagian besar perangkat, tetapi memberikan pengecualian intisari tak terbatas pada iOS 9.
Saya dapat mereproduksi di iPad Air 2 dan iPad generasi ke-4 dengan iOS 9 beta 2.
Saya menyadari itu mungkin masalah di iOS, tetapi mungkin masih perlu diselidiki.

iOS $location bug

Komentar yang paling membantu

Punya sedikit lebih jauh tentang yang satu ini. Saya telah membuat perubahan di Angular mengenai lokasi.
Di bagian "perbarui browser", saya telah mengubah $rootScope.$evalAsync menjadi $rootScope.$applyAsync.

Kedua metode tampaknya melakukan hal yang persis sama. Perbedaannya tidak menjadi jelas sampai Anda melihat eksekusi $digest yang sebenarnya. Saat AngularJS mengeksekusi intisari, ia berjalan di pohon Lingkup dan mengeksekusi $watch() binding hingga tidak ada lagi data kotor yang dihasilkan. Selama siklus hidup ini, baik antrian $applyAsync() dan antrian $evalAsync() di-flush; tapi, ini terjadi di dua tempat yang sangat berbeda.

Antrian $applyAsync() hanya di-flush di bagian atas $digest sebelum AngularJS mulai memeriksa data kotor. Dengan demikian, antrian $applyAsync() akan di-flush, paling banyak, satu kali selama $digest dan hanya akan dihapus jika antrian sudah diisi sebelum $digest dimulai.

Antrian $evalAsync(), di sisi lain, di-flush di bagian atas while-loop yang mengimplementasikan "dirty check" di dalam $digest. Ini berarti bahwa ekspresi apa pun yang ditambahkan ke antrian $evalAsync() selama intisari akan dieksekusi pada titik berikutnya dalam intisari yang sama.

Untuk membuat perbedaan ini lebih nyata, itu berarti ekspresi asinkron yang ditambahkan oleh $evalAsync() dari dalam pengikatan $watch() akan dieksekusi dalam intisari yang sama. Ekspresi asinkron yang ditambahkan oleh $applyAsync() dari dalam pengikatan $watch() akan dieksekusi di lain waktu (~10ms).

Semoga ini sudah membantu sebagian dari Anda :-).


// update browser
    $rootScope.$watch(function $locationWatch() {
      var oldUrl = trimEmptyHash($browser.url());
      var newUrl = trimEmptyHash($location.absUrl());
      var oldState = $browser.state();
      var currentReplace = $location.$$replace;
      var urlOrStateChanged = oldUrl !== newUrl ||
        ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);

      if (initializing || urlOrStateChanged) {
        initializing = false;

        $rootScope.$applyAsync(function() {
          var newUrl = $location.absUrl();
          var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
              $location.$$state, oldState).defaultPrevented;

          // if the location was changed by a `$locationChangeStart` handler then stop
          // processing this location change
          if ($location.absUrl() !== newUrl) return;

          if (defaultPrevented) {
            $location.$$parse(oldUrl);
            $location.$$state = oldState;
          } else {
            if (urlOrStateChanged) {
              setBrowserUrlWithFallback(newUrl, currentReplace,
                                        oldState === $location.$$state ? null : $location.$$state);
            }
            afterLocationChange(oldUrl, oldState);
          }
        });
      }

      $location.$$replace = false;

      // we don't need to return anything because $evalAsync will make the digest loop dirty when
      // there is a change
    });

Semua 154 komentar

Saya menemui masalah serupa, yang terjadi pada ios 9, tetapi berjalan dengan baik di perangkat lain.

Saya mereproduksi masalah ini dengan kode yang sama yang disediakan oleh santaslow pada 1.4.1 / ios 9:

<!DOCTYPE html>
<html>
<head>
    <script src="../static/js/angular/angular.1.4.1.js"></script>
    <script src="../static/js/angular-route/angular-route.1.4.1.js"></script>
    <script>
        angular.module('fail', ['ngRoute'])
                .config(function ($routeProvider) {
                    $routeProvider
                            .when('/a', {
                                template: '<a ng-href="#/b">a</a>'
                            })
                            .when('/b', {
                                template: '<a ng-href="#/a">b</a>'
                            })
                            .otherwise({
                                redirectTo: '/a'
                            });
                }).factory('$exceptionHandler', ['$log', function($log) {
                    return function(exception, cause) {
                        var message = 'angularjs exception: '+exception.message+': caused by "' + cause+ '\njs stack:\n'+exception.stack;
                        $log.error(message);
                    };
                }]);
    </script>
</head>
<body ng-app="fail">
<div ng-view></div>
</body>
</html>

Kode di atas berjalan normal di browser desktop, android dan ios 8 webview, tetapi pada ios 9 akan mengeluarkan pengecualian ketika saya mengklik tautan:

2015-07-02 11:00:09 ... angularjs exception: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []
http://errors.angularjs.org/1.4.1/$rootScope/infdig?p0=10&p1=%5B%5D: caused by "undefined
js stack:
file:///.../static/js/angular/angular.js:68:32
$digest<strong i="10">@file</strong>:///.../static/js/angular/angular.js:15705:35
$apply<strong i="11">@file</strong>:///.../static/js/angular/angular.js:15935:31
file:///.../static/js/angular/angular.js:12070:30
eventHandler<strong i="12">@file</strong>:///.../static/js/angular/angular.js:3264:25

Saya tidak dapat lagi mereproduksi di iOS 9 Beta 3.

Saya menerima kesalahan yang sama dengan ios9 beta publik (13A4293g)

Saya memverifikasi kode di atas pada ios 9 beta 3 (13A4293g), tidak terkecuali lagi. Tetapi aplikasi dengan menggunakan ng-view masih memberikan pengecualian infdig pada ios 9 beta 3.

Saya menerima kesalahan yang sama dengan ios9 beta publik (13A4293g)

Kesalahan: [$ rootScope:infdig ] 10 $digest() iterasi tercapai. Membatalkan!
Pengamat dipecat dalam 5 iterasi terakhir: []
http://errors.angularjs.org/1.3.13/ $rootScope/infdig?p0=10&p1=%5B%5D
file:///Users/mac5/Library/Developer/CoreSimulator/Devices/749DE7E3-D93F-47F9-A1FC-E3D54A1CCEEE/data/Containers/Bundle/Application/9B5EE368-F2A0-4C99-807B-EA17B2479E58/BA /lib/ionic/js/ionic.bundle.js:8762:32
$digest@file :///Users/mac5/Library/Developer/CoreSimulator/Devices/749DE7E3-D93F-47F9-A1FC-E3D54A1CCEEE/data/Containers/Bundle/Application/9B5EE368-F2A0-4C99Shops.E58/BAB2479E58/BAB2479B-EA17B app/www/lib/ionic/js/ionic.bundle.js:22980:35
$apply@file :///Users/mac5/Library/Developer/CoreSimulator/Devices/749DE7E3-D93F-47F9-A1FC-E3D54A1CCEEE/data/Containers/Bundle/Application/9B5EE368-F2A0-4C99-807B-EA17B2479 app/www/lib/ionic/js/ionic.bundle.js:23205:31
file:///Users/mac5/Library/Developer/CoreSimulator/Devices/749DE7E3-D93F-47F9-A1FC-E3D54A1CCEEE/data/Containers/Bundle/Application/9B5EE368-F2A0-4C99-807B-EA17B2479E58/BA /lib/ionic/js/ionic.bundle.js:54879:24
eventHandler@file :
dispatchEvent@[kode asli]
triggerMouseEvent@file :
tapClick@file :
tapTouchEnd@file :

Kami juga menerima kesalahan ini pada Beta 3 publik iOS 9 dengan aplikasi Angular kami sendiri. Itu tidak terjadi di iOS 8.

Sebagai solusinya, saya menulis arahan sederhana untuk mengganti ng-view dan angular-route.js. Solusinya bekerja dengan baik di aplikasi kita sendiri, semua pengecualian infdig menghilang di ios 9 beta/beta 3. Di bawah ini adalah kode yang disederhanakan, yang hanya untuk aplikasi kita sendiri, kasus penggunaan umum tidak dipertimbangkan. Saya TIDAK merekomendasikan orang lain untuk menggunakan ini:

(function (window) {
    'use strict';

    var myApp = angular.module("myApp");
    var $route = {};

    // replace $routeProvider.when with the function below:
    window.routeWhen = function(path, route) {
        $route[path] = route;
    };

    myApp.directive("myView", ['$compile', '$controller', '$http', '$rootScope', function ($compile, $controller, $http, $rootScope) {

        return {
            priority: -400,
            link: function (scope, element) {
                var parentScope = scope;
                scope = null;

                window.updateView = function (path) {
                    location.hash = '#'+url;
                    if (scope) scope.$destroy();
                    scope = parentScope.$new();

                    var route = $route[path];

                    var linkView = function(html) {
                        element.html(html);
                        var link = $compile(element.contents());
                        var controller = $controller(route.controller, {$scope: scope});
                        element.data('$ngControllerController', controller);
                        element.children().data('$ngControllerController', controller);
                        link(scope);
                        scope.$emit('$viewContentLoaded');
                        if (!$rootScope.$$phase && !scope.$$phase) scope.$apply();
                    };
                    if (route.templateCache) linkView(route.templateCache)
                    else if (route.template) {
                        route.templateCache = document.getElementById(route.template).innerHTML;
                        linkView(route.templateCache)
                    }
                    else $http.get(route.templateUrl;).success(function(html) {
                        route.templateCache = html;
                        linkView(html);
                    });
                };
                //updateView(initialPath);
                // call updateView(path) to set location at other places of the app
            }
        };
    }]);

})(window)

Baru saja menginstal iOS 9 Beta 4 dan masih memiliki masalah yang sama. Ada orang lain?

Saya melihatnya di iOS 9 Beta 3 dan saya masih melihatnya di iOS 9 Beta 4.

+1

Ya, kami juga melihat masalah yang sama bahkan dengan router ui sudut. Adakah yang punya solusi yang valid untuk masalah ini untuk sementara?

Melihat masalah yang sama di uiWebView pada iOS9 terbaru.

Apakah ada yang punya pembaruan tentang masalah ini?

Ini masih menjadi masalah. Pembukaan kembali

Sepertinya masalah ios. Apakah ini dilacak di webkit di suatu tempat?

+1

+1

Sama disini. Aplikasi Cordova kami berjalan dengan baik jika berjalan sebagai web di Safari iPad, tetapi intisari tak terbatas terjadi jika berjalan sebagai aplikasi Cordova (UIWebView).

Masalah yang persis sama dengan @borrull ! Sudah bereksperimen dengan WKWebView dan kemudian masalahnya tidak ada. Tetapi kami tidak dapat menggunakan WKWebView karena kami memerlukan Local File Serving (dan kami tidak ingin menjalankan server lokal di aplikasi kami) dan cookie. Jadi itu harus melakukan sesuatu dengan UIWebView dalam kombinasi dengan Cordova/Mobile Safari di iOS 9. Saat ini saya sedang men-debug $locationWatch di Angular karena saya melihat bahwa aplikasi kami ingin bertransisi ke lokasi yang berbeda beberapa kali dan kemudian (setelah 10 kali ) kesalahan intisari dilemparkan.

masalah yang sama di sini di iOS9 béta4
Angular tak terbatas $digest loop ;(

+1, hanya di UIWebView, bukan di WKWebView tetapi kami hanya dapat menggunakan UIWebView di aplikasi cordova kami.

+1

Jika ini adalah masalah khusus iOS, silakan buka masalah di pelacak masalah webkit dan berikan demo! +1 di sini kemungkinan tidak akan mengubah apa pun, karena ini benar-benar terdengar seperti bug browser.

Apakah seseorang melaporkan bug ini ke Apple untuk diselidiki?

Saya melaporkan bug ini ke apple. Tapi mungkin Anda semua harus melakukan hal yang sama untuk mendapatkan perhatian mereka pada bug tersebut.

Bisakah Anda memberi kami tautan sehingga kami dapat memberi +1?

Itu ada di akun apel pribadi kami melalui reporter bug .. jadi tidak ada tautan publik ;(

Bisakah Anda mempostingnya ke openradar dan membagikan id rdar agar kami dapat menipunya!

sama di iOS9 béta 5 :
bekerja di safari seluler
bekerja di WKWebview yang tidak dapat kami gunakan karena tidak dapat melayani file lokal dan tidak mendukung NSProtocol
bekerja BUKAN di UIWebView

sama di sini di iOS 9 Beta 5

Saya mengajukan bug dengan Apple juga. Tautan Open Radar adalah: https://openradar.appspot.com/22186109 (Ini akan membantu mereka yang malas mengajukan bug). Silakan tinggalkan komentar jika Anda dapat meningkatkan kata-kata/penjelasan bug ;-) Anda dapat mengunduh proyek Xcode untuk dilampirkan dengan pengarsipan bug pada tiket Open Radar (Terima kasih kepada @santaslow untuk JS di OP)

Saya telah membuat versi proyek Xcode yang sama (dari @borrull) tetapi dengan ui-router alih-alih ng-route. Masalah yang sama persis. Bagi yang berminat, Anda dapat menemukan proyeknya di sini: http://s000.tinyupload.com/index.php?file_id=87281871603760127355

Kami juga melihat masalah demikian. Saya dapat mengejar masalah menjadi bahwa properti location.* tidak segera diperbarui ketika angular ada dalam campuran. Jika Anda mencoba menetapkan nilai ke location.hash (seperti apa yang dilakukan di belakang layanan lokasi), maka segera baca kembali, nilainya tidak berubah. Tampaknya ada beberapa efek samping yang terjadi sebagai akibat dari penangan jqlite yang dilampirkan ke peristiwa popstate dan hashchanged.

Saya akan mencoba dan mengunggah sampel saat saya menggunakan komputer.

+1

@CleverCoder Ada pembaruan pada sampel?

Saya harus menyelesaikan kasus repro di pagi hari, karena kode saya telah diikat sepanjang akhir pekan. Terima kasih atas dorongannya! Saat iOS 9 menghitung mundur, kami memiliki kepentingan untuk melihat ini diselesaikan. Saya akan mengunggah sesuatu sesegera mungkin.

+1

Saya telah mereproduksi apa yang saya yakini sebagai penyebab utama, di mana pengaturan lokasi hash atau properti href tidak "berlaku" segera.
Berikut tautan ke proyek XCode:
https://www.dropbox.com/s/2jkwv2thhm86nly/iOS%209%20Location%20Bug.zip?dl=0
Beri tahu saya jika Anda tidak dapat mengakses file.

Amati nilai yang dihasilkan di location.hash, serta lampirkan Safari ke debug. Tampaknya ada sesuatu yang menunda perubahan sebagai akibat dari beberapa acara yang didasarkan pada acara 'popstate' dan 'hashchange'.

Saya harap ini bermanfaat.

  • Sean

Kami menggunakan window.location.href alih-alih menggunakan state.go dan tampaknya berfungsi untuk saat ini. Kurang buggy.

Nilai location.hash akan benar setelah putaran runloop. Angular dapat dengan mudah mengatasi masalah ini dengan menunda location.hash get di setTimeout(..., 0). Saya pikir ini akan menjadi ~2 perubahan pada angular.js/src/ng/location.js.

@hober Mencoba batas waktu dengan sudut seperti ini:

// update $location when $browser url changes
    $browser.onUrlChange(function(newUrl, newState) {
      $rootScope.$evalAsync(function() {
        var oldUrl = $location.absUrl();
        var oldState = $location.$$state;
        var defaultPrevented;

        $location.$$parse(newUrl);
        $location.$$state = newState;

        defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
            newState, oldState).defaultPrevented;

        // if the location was changed by a `$locationChangeStart` handler then stop
        // processing this location change
        if ($location.absUrl() !== newUrl) return;

        if (defaultPrevented) {
          $location.$$parse(oldUrl);
          $location.$$state = oldState;
          setTimeout(function(){ setBrowserUrlWithFallback(oldUrl, false, oldState) }, 0);
        } else {
          initializing = false;
          afterLocationChange(oldUrl, oldState);
        }
      });
      if (!$rootScope.$$phase) $rootScope.$digest();
    });

dan

// update browser
    $rootScope.$watch(function $locationWatch() {
      var oldUrl = trimEmptyHash($browser.url());
      var newUrl = trimEmptyHash($location.absUrl());
      var oldState = $browser.state();
      var currentReplace = $location.$$replace;
      var urlOrStateChanged = oldUrl !== newUrl ||
        ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);

      if (initializing || urlOrStateChanged) {
        initializing = false;

        $rootScope.$evalAsync(function() {
          var newUrl = $location.absUrl();
          var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
              $location.$$state, oldState).defaultPrevented;

          // if the location was changed by a `$locationChangeStart` handler then stop
          // processing this location change
          if ($location.absUrl() !== newUrl) return;

          if (defaultPrevented) {
            $location.$$parse(oldUrl);
            $location.$$state = oldState;
          } else {
            if (urlOrStateChanged) {
              setTimeout(function(){ setBrowserUrlWithFallback(newUrl, currentReplace,
                  oldState === $location.$$state ? null : $location.$$state) }, 0);
            }
            afterLocationChange(oldUrl, oldState);
          }
        });
      }

      $location.$$replace = false;

      // we don't need to return anything because $evalAsync will make the digest loop dirty when
      // there is a change
    });

Jadi saya menambahkan setTimout di sekitar metode setBrowserUrlWithFallback tetapi tidak menyelesaikan masalah.

Berikut adalah kasus uji yang dikurangi yang tidak bergantung pada Angular, dan itu menunjukkan solusinya. Bagaimana sebenarnya mengimplementasikan solusi di Angular tidak jelas bagi saya. https://Gist.github.com/hober/a29b6c28ac1744c800dd

Punya sedikit lebih jauh tentang yang satu ini. Saya telah membuat perubahan di Angular mengenai lokasi.
Di bagian "perbarui browser", saya telah mengubah $rootScope.$evalAsync menjadi $rootScope.$applyAsync.

Kedua metode tampaknya melakukan hal yang persis sama. Perbedaannya tidak menjadi jelas sampai Anda melihat eksekusi $digest yang sebenarnya. Saat AngularJS mengeksekusi intisari, ia berjalan di pohon Lingkup dan mengeksekusi $watch() binding hingga tidak ada lagi data kotor yang dihasilkan. Selama siklus hidup ini, baik antrian $applyAsync() dan antrian $evalAsync() di-flush; tapi, ini terjadi di dua tempat yang sangat berbeda.

Antrian $applyAsync() hanya di-flush di bagian atas $digest sebelum AngularJS mulai memeriksa data kotor. Dengan demikian, antrian $applyAsync() akan di-flush, paling banyak, satu kali selama $digest dan hanya akan dihapus jika antrian sudah diisi sebelum $digest dimulai.

Antrian $evalAsync(), di sisi lain, di-flush di bagian atas while-loop yang mengimplementasikan "dirty check" di dalam $digest. Ini berarti bahwa ekspresi apa pun yang ditambahkan ke antrian $evalAsync() selama intisari akan dieksekusi pada titik berikutnya dalam intisari yang sama.

Untuk membuat perbedaan ini lebih nyata, itu berarti ekspresi asinkron yang ditambahkan oleh $evalAsync() dari dalam pengikatan $watch() akan dieksekusi dalam intisari yang sama. Ekspresi asinkron yang ditambahkan oleh $applyAsync() dari dalam pengikatan $watch() akan dieksekusi di lain waktu (~10ms).

Semoga ini sudah membantu sebagian dari Anda :-).


// update browser
    $rootScope.$watch(function $locationWatch() {
      var oldUrl = trimEmptyHash($browser.url());
      var newUrl = trimEmptyHash($location.absUrl());
      var oldState = $browser.state();
      var currentReplace = $location.$$replace;
      var urlOrStateChanged = oldUrl !== newUrl ||
        ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);

      if (initializing || urlOrStateChanged) {
        initializing = false;

        $rootScope.$applyAsync(function() {
          var newUrl = $location.absUrl();
          var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
              $location.$$state, oldState).defaultPrevented;

          // if the location was changed by a `$locationChangeStart` handler then stop
          // processing this location change
          if ($location.absUrl() !== newUrl) return;

          if (defaultPrevented) {
            $location.$$parse(oldUrl);
            $location.$$state = oldState;
          } else {
            if (urlOrStateChanged) {
              setBrowserUrlWithFallback(newUrl, currentReplace,
                                        oldState === $location.$$state ? null : $location.$$state);
            }
            afterLocationChange(oldUrl, oldState);
          }
        });
      }

      $location.$$replace = false;

      // we don't need to return anything because $evalAsync will make the digest loop dirty when
      // there is a change
    });

Berikut pendekatan lain. Saya tidak begitu akrab dengan basis kode Angular, tetapi logikanya tampak rasional. Fungsi url(...) browser saat ini bergantung pada location.href yang segera mengembalikan URL yang benar. Karena metode ini dipanggil dalam run loop yang sama, dalam siklus stabilisasi $digest, metode ini terus mendapatkan URL lama. Patch ini memanfaatkan 'pendingHref' untuk melacak tugas, mengembalikan nilai itu sebagai gantinya, jika disetel. Setelah nilai disejajarkan dengan location.href, nilai tertunda dihapus. Selama satu set url, timer disetel dengan 0ms untuk menangkap kasus di mana url() get tidak dipanggil. Ini tidak sempurna, tetapi logika tampaknya bekerja. Ini terutama untuk mempertimbangkan pendekatan alternatif yang tidak membuat penundaan kinerja. Ini didasarkan pada tag Angular v1.4.3.

diff --git a/src/ng/browser.js b/src/ng/browser.js
index 928de95..3b9957e 100644
--- a/src/ng/browser.js
+++ b/src/ng/browser.js
@@ -87,7 +87,9 @@ function Browser(window, document, $log, $sniffer) {
   var cachedState, lastHistoryState,
       lastBrowserUrl = location.href,
       baseElement = document.find('base'),
-      reloadLocation = null;
+      reloadLocation = null,
+      pendingHref = null,
+      pendingHrefTimer = null;

   cacheState();
   lastHistoryState = cachedState;
@@ -124,6 +126,18 @@ function Browser(window, document, $log, $sniffer) {
     if (location !== window.location) location = window.location;
     if (history !== window.history) history = window.history;

+    // Schedule cleaning up pendingHref on the next run loop for setting URL. This is to handle
+    // the case where the browser doesn't update the location.* properties immediately
+    if (!pendingHrefTimer && pendingHref && url) {
+      pendingHrefTimer = setTimeout(function () {
+        if (location.href == pendingHref) {
+          console.log('Actual href updated... setting pendingHref to null from setTimeout');
+          pendingHref = null;
+        }
+        pendingHrefTimer = null;
+      }, 0);
+    }
+
     // setter
     if (url) {
       var sameState = lastHistoryState === state;
@@ -147,6 +161,7 @@ function Browser(window, document, $log, $sniffer) {
         // Do the assignment again so that those two variables are referentially identical.
         lastHistoryState = cachedState;
       } else {
+        pendingHref = url;
         if (!sameBase || reloadLocation) {
           reloadLocation = url;
         }
@@ -161,10 +176,22 @@ function Browser(window, document, $log, $sniffer) {
       return self;
     // getter
     } else {
+      var href = location.href.replace(/%27/g, "'");
+      if (pendingHref) {
+        //console.log('.. using pendingHref for url() return value');
+        href = pendingHref;
+      }
+
+      if (location.href == pendingHref) {
+        console.log('Actual href updated... setting pendingHref to null in getter');
+        pendingHref = null;
+      }
+
+      //var href = location.href.replace(/%27/g,"'");
       // - reloadLocation is needed as browsers don't allow to read out
       //   the new location.href if a reload happened.
       // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
-      return reloadLocation || location.href.replace(/%27/g,"'");
+      return reloadLocation || href;
     }
   };

Terima kasih @CleverCoder untuk solusinya! Tampaknya bekerja seperti pesona! :+1:

@CleverCoder
akan lebih bagus jika Anda melakukan permintaan tarik dengan ini ke tim sudut.

@viattik Saya agak terkejut jika tim sudut akan mengadopsi solusi untuk UIWebView di iOS9 karena bug ada di UIWebView (Apple) itu sendiri. Tapi Anda selalu bisa mencoba ...

@raftheunis87
Ada banyak bug di browser yang berbeda dan banyak solusi untuk bug tersebut dalam kode sudut.
Meskipun mereka tidak secara resmi mendukung UIWebView, banyak aplikasi hybrid akan rusak dan menggunakan angular tidak mungkin dilakukan di aplikasi hybrid di iOS terbaru sampai Apple memperbaiki bug itu. Dan itu masalah yang cukup besar menurut saya.
Jadi saya akan mencobanya.

@viattik saya sangat setuju. Dan btw: Apple memberi tahu kami bahwa kecil kemungkinan mereka akan memperbaiki bug UIWebView. Jadi memang: cobalah ;-)

Teman-teman, jika Anda dapat memposting ini sebagai bug webkit, idealnya dengan kasus repro, saya akan menindaklanjuti dengan beberapa kontak kami di sisi WebKit. https://bugs.webkit.org/

@naomiblack
Tidak yakin apakah itu bug webkit. Karena itu hanya terjadi di UIWebView di iOS9. Safari di iOS9 berfungsi dengan baik.

@raftheunis87 terima kasih atas saran kode Anda, bekerja dengan sempurna

@ raftheunis87 @CleverCoder adalah thr cara untuk bekerja dengan ion-sudut? bisa lebih spesifik?

@abrahamrkj Saya tidak punya pengalaman dengan ionic. Tetapi apakah penyesuaiannya bersudut saat menggunakan ionik? Kalau tidak, saya akan mengatakan bahwa perbaikan yang sama akan bekerja dengan sudut ionik ...

@raftheunis87 https://github.com/driftyco/ionic/tree/master/js ini adalah sudut yang mereka gunakan.

@CleverCoder +1 untuk permintaan tarik. Saya setuju dengan @viattik bahwa ini adalah masalah penting karena akan merusak banyak aplikasi hybrid.

Permintaan tarik mungkin dalam waktu dekat, meskipun saya ragu karena saya tidak sedekat basis kode Angular seperti yang lain. Saya akan segera meninjau kembali solusinya dan mencoba membuatnya anti peluru. Tampaknya aneh bahwa properti pada objek window.location tidak berubah 'segera'. Dalam pengujian yang saya lakukan, saya memperhatikan bahwa perubahan itu tetap ada selama kait acara 'popstate' dan 'hashchange' tidak ada, membuat saya berpikir bahwa penyebab perubahan yang ditangguhkan mungkin sebenarnya melakukan sesuatu lain.. Mungkin waktu peristiwa itu telah berubah (saya pikir itulah yang saya amati).
Saya akan menonton ini selama beberapa hari ke depan, dan jika tidak ada yang lebih baik muncul, saya akan menggali lebih dalam untuk mengkonfirmasi apa yang saya ketahui sejauh ini, dan bahwa tidak ada tempat yang lebih baik untuk mengatasi perubahan perilaku. Maaf jika ini membingungkan. Ada banyak hal yang terjadi di bawah tenda yang masih belum sepenuhnya saya pahami sehubungan dengan peristiwa itu.
Bersulang!

... dan ya, @borrull , saya setuju. Jika Apple tidak membuat perubahan lagi, maka ini adalah bom waktu yang serius yang akan benar-benar mengarah pada pers dan penunjuk jari yang buruk. Saya bukan penggemar penghitung waktu sebagai solusi (saya lebih suka meningkatkan aliran logika di sekitar properti bawaan ini), tetapi jika kita tidak dapat bergantung pada perubahan nilai setelah disetel, lalu di mana kita menggambar garis? Properti apa lagi yang tidak bisa kita percayai? Ini aneh.

@CleverCoder Hanya ingin mengucapkan terima kasih, tambalan Anda benar-benar menyelamatkan hari!

@CleverCoder Terima kasih atas solusi yang diberikan.

Saya mendapatkan solusi yang menggunakan fitur dekorator dari sudut dan datang tanpa menambal sumber sudut.

Dengan cssua pengaturan ini dapat dikonfigurasi untuk digunakan hanya di lingkungan tertentu.

    app.config(['$provide', ($provide) => {
        $provide.decorator('$browser', ['$delegate', ($delegate) => {
            var origUrl = $delegate.url;

            var pendingHref = null;
            var pendingHrefTimer = null;

            var newUrl = function (url, replace, state) {

                if (url) {
                    // setter
                    var result = origUrl(url, replace, state);

                    if (window.location.href != url) {

                        if (pendingHref != url) {
                            pendingHref = url;

                            if (pendingHrefTimer) clearTimeout(pendingHrefTimer);

                            pendingHrefTimer = setTimeout(function () {
                                if (window.location.href == pendingHref) {
                                    pendingHref = null;
                                }
                                pendingHrefTimer = null;
                            }, 0);
                        }
                    }

                    return result;
                } else {
                    // getter
                    if (pendingHref == window.location.href) {
                        pendingHref = null;
                    }

                    return pendingHref || origUrl(url, replace, state);
                }
            };

            $delegate.url = newUrl;

            return $delegate;
        }]);
    }]);

@CleverCoder See # 12635

@jd-carroll: Itu sangat menarik. Saya mungkin akan meninjau kembali ini sedikit nanti hari ini ketika saya punya waktu. Cukup dibanjiri barang. Itu hanya menciptakan lebih banyak misteri, karena itu sepertinya masalah terpisah yang seharusnya tidak menyebabkan penundaan lokasi.* nilai memperbarui.

@realityfilter : Lucu Anda menyebutkan dekorator... Saya baru saja selesai mengimplementasikan sesuatu menggunakan fungsionalitas dekorator Angular. Bagus!

Hai semua,
Saya hanya ingin menambahkan bahwa perbaikan ini memperkenalkan bug dalam kode kami yang mudah diperbaiki.

Template kami memiliki tag jangkar yang menggunakan href="#" dan ng-click="someCall()". href menyebabkan situs membuka index.html menggunakan perbaikan ini. Menghapus href memperbaiki masalah.

Aplikasi kami rusak selama navigasi tombol kembali di Ionic, pertama-tama pergi ke tampilan baru kemudian kembali ke tampilan lama sebagian dan kemudian kembali lagi ke tampilan baru di IOS9 beta resolusi apa pun untuk Ionic

Masalah yang sama dengan iOS 9 beta 5 13A4325c, Angular 1.4.0 (dengan cordova-ios 3.9.1). Semoga bug UIWebView yang mendasarinya akan diperbaiki!

Masalah yang sama terjadi pada Angular v1.2.27

Saya telah melacaknya ke rilis 1.2.27, bug tidak ada di rilis 1.2.26 sebelumnya.

Secara khusus, komit ini adalah pelakunya.

@damrbaby Sepertinya saya ada hubungannya dengan itu.

Tetapi fakta bahwa ia bekerja dengan versi terbaru dari angular di Mobile Safari menjelaskan bahwa ada hubungannya dengan uiWebView di iOS 9. Jadi perubahan yang mereka buat dalam kode sumber Angular tidak selalu merupakan hal yang buruk.

@CleverCoder @realityfilter @ jyc66 Aku hanya ingin mengucapkan terima kasih, Anda baru saja menyelamatkan saya hari.

Masalah masih ada di iOS9 GM Seed jadi perbarui aplikasi Anda!

Saya dapat mengonfirmasi, bahwa masalahnya masih ada di iOS9 GM (13A340)

Jadi ini berarti Apple memecahkan sesuatu dan kami harus memperbarui aplikasi kami lagi (beberapa di antaranya tidak berubah selama berbulan-bulan atau bahkan lebih dari setahun) agar tidak mogok. Masuk akal :( . Saya lebih suka Apple memperbaikinya untuk peluncuran iOS9. Pergi ke versi Angular terbaru di aplikasi lama pasti akan merusak beberapa hal lain juga.

Saya sangat ragu Angular adalah satu-satunya kerangka kerja yang mengalami masalah dengan iOS9?

Jadi, @adamdbradley , @perrygovier , dan @mhartington dari Tim Ionic telah bekerja sepanjang hari pada perbaikan yang akan bekerja untuk Ionic dan juga untuk aplikasi Angular biasa. Tujuannya adalah untuk menjadi perbaikan drop-in yang tidak memerlukan modifikasi Angular, dan akan (semoga) bekerja di sebagian besar versi 1.2+ Angular.

Berikut adalah solusi paket kami saat ini yang menghiasi dan memperbaiki $browser dengan menerapkan tambalan ini . Catatan: ini didasarkan pada Angular 1.4.3 dan semacam "klon dengan perbaikan" dari browser.js dari Angular yang tepat: https://github.com/driftyco/ionic/blob/ios9-patch/js /angular/service/decorators/ios9-browser-fix.js

Kami juga menempatkan tambalan di CDN kami. Saya tidak menyarankan menggunakan file CDN untuk produksi, itu hanya ada sehingga lebih mudah untuk menguji dengan sekarang.

Untuk mengujinya, letakkan tag skrip ini di bawah file angular atau ionic.bundle.js Anda:

<script src="https://code.ionicframework.com/patch/ios9-$browser-patch.js"></script>

Juga, sekarang ini menerapkan tambalan apakah Anda menjalankan iOS9 atau tidak. Itu akan segera diperbaiki sehingga hanya berjalan di iOS 9 UIWebView.

Ikuti masalah Ionic yang sesuai di sini: https://github.com/driftyco/ionic/issues/4082#issuecomment -139079725

Halo semua,

UI-sref berfungsi seperti pesona tetapi $state.go merusak animasi tombol kembali
dan halaman sering berkedip bahkan setelah menerapkan perbaikan ini.

Salam,
Ajay Singh

Pada Kamis, 10 Sep 2015 pukul 06:23, Max Lynch [email protected] menulis:

Jadi, @adamdbradley https://github.com/adamdbradley , @perrygovier
https://github.com/perrygovier , dan @mhartington
https://github.com/mhartington dari Tim Ionic telah bekerja
sepanjang hari pada perbaikan yang akan berfungsi untuk Ionic dan untuk aplikasi Angular biasa sebagai
baik. Tujuannya adalah untuk menjadi perbaikan drop-in yang tidak memerlukan modifikasi
Angular, dan akan (semoga) berfungsi di sebagian besar versi 1.2+ Angular.

Inilah solusi paket kami saat ini yang menghiasi dan memperbaiki $browser dengan
menerapkan tambalan ini
https://github.com/angular/angular.js/issues/12241#issuecomment -130744518.
Catatan: ini didasarkan pada Angular 1.4.3 dan merupakan semacam "klon dengan perbaikan" dari
browser.js dari Angular yang tepat:
https://github.com/driftyco/ionic/blob/ios9-patch/js/angular/service/decorators/ios9-browser-fix.js

Kami juga menempatkan tambalan di CDN kami. Saya tidak menyarankan menggunakan file CDNN
untuk produksi, hanya ada di sana sehingga lebih mudah untuk mengujinya sekarang.

Silakan mengujinya dan beri tahu kami bagaimana kelanjutannya, terima kasih.

Untuk mengujinya, letakkan tag skrip ini di bawah sudut atau
file ionic.bundle.js:

Masalah terkait

jetta20162 picture jetta20162  ·  3Komentar

guyandtheworld picture guyandtheworld  ·  3Komentar

jtorbicki picture jtorbicki  ·  3Komentar

kishanmundha picture kishanmundha  ·  3Komentar

ceymard picture ceymard  ·  3Komentar