以下简单的 HTML 演示了该问题:
<!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>
这在大多数设备上按预期运行,但在 iOS 9 上会引发无限摘要异常。
我可以在装有 iOS 9 beta 2 的 iPad Air 2 和 iPad 4 代上重现。
我意识到这可能是 iOS 中的一个问题,但它可能仍然值得调查。
我遇到了类似的问题,它发生在 ios 9 上,但在其他设备上运行正常。
我用 santaslow 在 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>
上面的代码在桌面浏览器、android和ios 8 webview上正常运行,但在ios 9上点击链接时会抛出异常
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
我无法再在 iOS 9 Beta 3 中重现。
我在 ios9 public beta (13A4293g) 上收到同样的错误
我在 ios 9 beta 3 (13A4293g) 上验证了上面的代码,不再例外。 但是使用 ng-view 的应用程序仍然在 ios 9 beta 3 上抛出 infdig 异常。
我在 ios9 public beta (13A4293g) 上收到同样的错误
错误:[$ rootScope:infdig ] 10 $digest() 迭代达到。 中止!
在最后 5 次迭代中触发的观察者:[]
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-EA17E3D54A1CCEEE/data/Containers/Bundle/Application/9B5EE368-F2A0-4C99-807B-EA17E3D54A1CCEEE /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-4C99-8072B-4E1A1HOP 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-47E3Hop 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-EA17E3D54A1CCEEE/data/Containers/Bundle/Application/9B5EE368-F2A0-4C99-807B-EA17E3D54A1CCEEE /lib/ionic/js/ionic.bundle.js:54879:24
eventHandler@file :///Users/mac5/Library/Developer/CoreSimulator/Devices/749DE7E3-D93F-47F9-A1FC-E3D54A1CCEEE/data/Containers/Bundle/Application/9B5EE368-F2A0-4C99-807B-4BA9E75B /www/lib/ionic/js/ionic.bundle.js:11713:25
dispatchEvent@[本机代码]
triggerMouseEvent@file :
tapClick@file :
tapTouchEnd@file :
我们也在使用我们自己的 Angular 应用程序的 iOS 9 的公共 Beta 3 上收到此错误。 它不会发生在 iOS 8 中。
作为一种解决方法,我编写了一个简单的指令来替换 ng-view 和 angular-route.js。 该解决方案在我们自己的应用程序中运行良好,所有 infdig 异常在 ios 9 beta/beta 3 上都消失了。以下是简化代码,仅针对我们自己的应用程序,不考虑一般用例。 我不推荐其他人使用这个:
(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)
刚刚安装了 iOS 9 Beta 4 并且仍然有同样的问题。 还有谁?
我在 iOS 9 Beta 3 中看到它,我仍然在 iOS 9 Beta 4 中看到它。
+1
是的,即使使用 angular ui 路由器,我们也看到了同样的问题。 在此期间,是否有人对此问题有有效的解决方法?
在最新的 iOS9 上的 uiWebView 中看到同样的问题。
有没有人对此问题有任何更新?
这仍然是一个问题。 重新开放
好像是ios的问题。 这是在某个地方的 webkit 上跟踪的吗?
+1
+1
同样在这里。 如果在 iPad Safari 上作为网络运行,我们的 Cordova 应用程序运行良好,但如果它作为 Cordova 应用程序 (UIWebView) 运行,则会发生无限摘要。
与@borrull完全相同的问题! 已经用 WKWebView 进行了试验,然后问题就不存在了。 但是我们不能使用 WKWebView,因为我们需要本地文件服务(并且我们不想在我们的应用程序中运行本地服务器)和 cookie。 所以它必须在 iOS 9 上将 UIWebView 与 Cordova/Mobile Safari 结合起来做一些事情。我目前正在 Angular 中调试 $locationWatch,因为我看到我们的应用程序想要多次转换到不同的位置,然后(10 次之后) ) 抛出摘要错误。
在 iOS9 beta4 上也有同样的问题
角度无限 $digest 循环 ;(
+1,仅在 UIWebView 中,不在 WKWebView 中,但我们只能在我们的cordova 应用程序中使用 UIWebView。
+1
如果这是 iOS 特定问题,请在 webkit 问题跟踪器上打开问题并提供演示! +1 在这里不太可能改变任何东西,因为它真的听起来像一个浏览器错误。
有人向 Apple 报告了此错误以进行调查吗?
我向苹果报告了这个错误。 但也许你们都应该做同样的事情来引起他们对错误的关注。
你能给我们一个链接以便我们可以 +1 吗?
它通过错误报告器在我们的个人苹果帐户中..所以没有公共链接;(
你能把它发布到 openradar 并分享 rdar id 以便我们可以欺骗它!
在 iOS9 测试版 5 上相同:
适用于移动 Safari
适用于我们无法使用的 WKWebview,因为它无法提供本地文件并且不支持 NSProtocol
不适用于 UIWebView
在 IOS 9 Beta 5 上也一样
我也向 Apple 提交了一个错误。 Open Radar 链接是: https : @santaslow在 OP 中提供 JS)
我已经创建了相同 Xcode 项目的一个版本(来自@borrull),但使用 ui-router 而不是 ng-route。 完全一样的问题。 有兴趣的朋友可以在这里找到项目: http :
我们也看到了这样的问题。 我能够将问题归结为 location.* 属性在 angular 混合时不会立即更新。 如果您尝试为 location.hash 分配一个值(就像在定位服务后面所做的那样),然后立即读回它,该值没有改变。 由于 jqlite 处理程序附加到 popstate 和 hashchanged 事件,似乎会发生一些副作用。
当我在电脑上时,我会尝试上传一个样本。
+1
@CleverCoder样本有任何更新吗?
我必须在早上完成复制案例,因为我整个周末都在使用代码。 谢谢你的轻推! 随着 iOS 9 倒计时,我们有兴趣看到这个问题的解决。 我会尽快上传一些东西。
+1
我已经重现了我认为的根本原因,即设置位置哈希或 href 属性不会立即“应用”。
这是 XCode 项目的链接:
https://www.dropbox.com/s/2jkwv2thhm86nly/iOS%209%20Location%20Bug.zip?dl=0
如果您无法访问该文件,请告诉我。
观察 location.hash 中的结果值,并附加 Safari 进行调试。 由于基于“popstate”和“hashchange”事件的某些事件管道,似乎有些东西推迟了更改。
我希望这是有帮助的。
我们正在使用 window.location.href 而不是 state.go 并且它现在似乎正在工作。 少越野车。
location.hash 的值将在 runloop 旋转后正确。 Angular 可以通过延迟 setTimeout(..., 0) 中的 location.hash 来轻松解决这个问题。 我认为这将是对 angular.js/src/ng/location.js 的约 2 处更改。
@hober像这样尝试使用 angular 超时:
// 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();
});
和
// 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
});
所以我在 setBrowserUrlWithFallback 方法周围添加了一个 setTimout ,但它没有解决问题。
这是一个不依赖于 Angular 的简化测试用例,它演示了解决方法。 我不清楚如何在 Angular 中实际实施解决方法。 https://gist.github.com/hober/a29b6c28ac1744c800dd
在这一点上更进一步。 我在 Angular 中对位置进行了更改。
在“更新浏览器”部分,我将 $rootScope.$evalAsync 更改为 $rootScope.$applyAsync。
这两种方法看起来完全一样。 在您查看实际的 $digest 执行之前,差异不会变得明显。 当 AngularJS 执行摘要时,它会遍历 Scope 树并执行 $watch() 绑定,直到不再产生脏数据。 在这个生命周期中,$applyAsync() 队列和 $evalAsync() 队列都会被刷新; 但是,这发生在两个非常不同的地方。
$applyAsync() 队列只会在 AngularJS 开始检查脏数据之前在 $digest 的顶部刷新。 因此,$applyAsync() 队列将在 $digest 期间最多被刷新一次,并且只有在 $digest 开始之前队列已经被填充时才会被刷新。
另一方面,$evalAsync() 队列在实现 $digest 内部“脏检查”的 while 循环的顶部刷新。 这意味着在摘要期间添加到 $evalAsync() 队列的任何表达式都将在同一摘要中稍后执行。
为了使这种差异更加具体,这意味着 $evalAsync() 从 $watch() 绑定中添加的异步表达式将在相同的摘要中执行。 $applyAsync() 从 $watch() 绑定中添加的异步表达式将在稍后的时间点(~10ms)执行。
希望这已经对你们中的一些人有所帮助:-)。
// 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
});
这是另一种方法。 我对 Angular 代码库不太熟悉,但逻辑似乎很合理。 浏览器 url(...) 函数当前依赖于 location.href 立即返回正确的 URL。 因为这个方法是在同一个 run loop 中调用的,所以在 $digest 稳定周期内,它会继续获取旧的 URL。 此补丁利用“pendingHref”来跟踪分配,如果已设置,则返回该值。 一旦该值与 location.href 对齐,则清除挂起的值。 在一组 url 期间,定时器设置为 0ms 以捕获未调用 url() get 的情况。 这并不完美,但逻辑似乎有效。 这主要是为了考虑一种不会造成性能延迟的替代方法。 这是基于 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;
}
};
感谢@CleverCoder的解决方案! 似乎很有魅力! :+1:
@聪明的编码器
如果您向 angular 团队发出拉取请求,那就太好了。
@viattik如果 angular 团队会在 iOS9 上采用 UIWebView 的解决方法,我会感到惊讶,因为该错误出在 UIWebView (Apple) 本身中。 但是你可以随时尝试...
@raftheunis87
在不同的浏览器中有很多错误,并且有很多针对 angular 代码中的错误的解决方法。
尽管它们没有正式支持 UIWebView,但在 Apple 修复该错误之前,许多混合应用程序将被破坏,并且在最新的 iOS 中的混合应用程序中不可能使用 angular。 我会说这是一个非常大的问题。
所以我想试一试。
@viatik我完全同意。 顺便说一句:Apple 告诉我们,他们不太可能修复 UIWebView 错误。 确实如此:试一试;-)
伙计们,如果您可以将此作为 webkit 错误发布,最好使用重现案例,我将跟进我们在 WebKit 方面的一些联系人。 https://bugs.webkit.org/
@naomiblack
不确定这是否是 webkit 错误。 因为它只发生在 iOS9 上的 UIWebView 中。 iOS9 上的 Safari 工作正常。
@raftheunis87感谢您的代码建议,完美运行
@raftheunis87 @CleverCoder是一种使用 ionic-angular 的方法吗? 你可以说得更详细点吗?
@abrahamrkj我对离子没有任何经验。 但是当使用 ionic 时,他们的定制是否有角度? 否则,我会说相同的修复程序适用于 ionic-angular ......
@raftheunis87 https://github.com/driftyco/ionic/tree/master/js这是他们使用的角度。
@CleverCoder +1 用于拉取请求。 我同意@viattik 的观点,这是一个重要问题,因为它会破坏许多混合应用程序。
拉取请求可能在不久的将来,尽管我犹豫,因为我不像其他人那样接近 Angular 代码库。 我将很快重新审视该解决方案并尝试使其防弹。 window.location 对象上的属性不会“立即”更改,这似乎很奇怪。 在我所做的测试中,我确实注意到只要 'popstate' 和 'hashchange' 事件钩子没有到位,更改确实会保持不变,这让我认为延迟更改的原因实际上可能是做一些事情否则......也许这些事件的时间已经改变(我认为这就是我所观察到的)。
我将在接下来的几天内观察这个,如果没有更好的表面,我会更深入地挖掘以确认我目前所知道的,并且没有更好的地方来解决行为的变化。 对不起,如果这令人困惑。 关于这些事件,我仍然不完全理解在幕后发生的很多事情。
干杯!
...是的, @borrull ,我同意。 如果苹果不再做出任何改变,那么这就是一个严重的定时炸弹,将真正导致不良新闻和指责。 我不喜欢将计时器作为解决方法(我宁愿围绕这些内置属性改进逻辑流程),但是如果我们不能依赖设置后的值更改,那么我们在哪里绘制线? 还有哪些我们不能信任的属性? 这是一个奇怪的。
@CleverCoder只想说声谢谢,你的补丁真的拯救了这一天!
@CleverCoder感谢您提供的解决方法。
我派生了一个解决方案,它使用来自 angular 的装饰器功能,并且没有修补 angular 源。
使用cssua,可以将此设置配置为仅在特定环境中使用。
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见 #12635
@jd-carroll:这真的很有趣。 我可能会在今天晚些时候有时间的时候重新审视这个问题。 东西塞得满满当当。 这只会产生更多的神秘感,因为这似乎是一个单独的问题,不应导致位置延迟。* 值更新。
@realityfilter :有趣的是你提到了装饰器......我刚刚完成了使用 Angular 装饰器功能的实现。 好的!
大家好,
我只想补充一点,此修复程序在我们的代码中引入了一个易于修复的错误。
我们的模板有使用 href="#" 和 ng-click="someCall()" 的锚标签。 href 导致站点使用此修复程序转到 index.html。 删除 href 解决了这个问题。
我们的应用程序在 Ionic 中的后退按钮导航期间中断,它首先进入新视图,然后部分返回旧视图,然后在 IOS9 beta 上再次返回新视图 Ionic 的任何分辨率
与 iOS 9 beta 5 13A4325c、Angular 1.4.0(使用cordova-ios 3.9.1)相同的问题。 希望底层的 UIWebView 错误将得到修复!
同样的问题发生在 Angular v1.2.27
我已经将其追溯到 1.2.27 版本,该错误不在之前的 1.2.26 版本中。
具体来说,这次提交是罪魁祸首。
@damrbaby看起来我可以与它有关。
但是,它在 Mobile Safari 中使用最新版本的 angular 的事实清楚地表明,它必须对 iOS 9 上的 uiWebView 做一些事情。因此,他们在 Angular 源代码中所做的更改不一定是坏事。
@CleverCoder @realityfilter @jyc66我只想说谢谢你,你拯救了我的一天。
iOS9 GM Seed 上仍然存在问题,因此请让您的应用程序更新人员!
我可以确认,该问题仍然存在于 iOS9 GM (13A340)
所以这意味着 Apple 破坏了一些东西,我们必须再次更新我们的应用程序(其中一些已经几个月甚至一年多没有改变)以防止它们崩溃。 有道理:(。我宁愿让 Apple 在 iOS9 发布时修复它。在旧应用程序中使用最新的 Angular 版本也必然会破坏其他一些东西。
我非常怀疑 Angular 是唯一一个在 iOS9 上有问题的框架吗?
因此,来自 Ionic 团队的@adamdbradley 、 @perrygovier和@mhartington 一整天都在致力于修复,该修复适用于 Ionic 和普通的 Angular 应用程序。 目标是成为一个不需要修改 Angular 的插入式修复程序,并且(希望)适用于大多数 1.2+ Angular 版本。
这是我们当前的捆绑解决方案,它通过应用此补丁来装饰和修复$browser
。 注意:这是基于 Angular 1.4.3,是来自 Angular 的browser.js
的“带有修复的克隆”: https :
我们还将补丁放在我们的 CDN 上。 我不建议将 CDN 文件用于生产,它只是在那里,所以现在更容易测试。
要测试它,请将此脚本标记放在您的 angular 或 ionic.bundle.js 文件下方:
<script src="https://code.ionicframework.com/patch/ios9-$browser-patch.js"></script>
此外,现在无论您是否在 iOS9 上运行,它都会应用该补丁。 这将很快得到修复,使其仅在 iOS 9 UIWebView 上运行。
在此处关注相应的 Ionic 问题: https :
大家好,
UI-sref 就像一个魅力,但 $state.go 打破了后退按钮动画
即使在应用此修复程序后,页面也会闪烁很多。
问候,
阿杰·辛格
2015 年 9 月 10 日星期四上午 6:23,Max Lynch [email protected]写道:
所以, @adamdbradley https://github.com/adamdbradley,@perrygovier
https://github.com/perrygovier和 @mhartington
来自 Ionic 团队的https://github.com/mhartington一直在工作
一整天都在修复适用于 Ionic 和普通 Angular 应用程序的问题
出色地。 目标是成为一个不需要修改的直接修复
Angular,并且(希望)适用于大多数 1.2+ Angular 版本。这是我们当前的捆绑解决方案,它通过以下方式装饰和修复 $browser
应用这个补丁
https://github.com/angular/angular.js/issues/12241#issuecomment -130744518。
注意:这是基于 Angular 1.4.3,是一种“带有修复的克隆”
来自 Angular 的 browser.js:
https://github.com/driftyco/ionic/blob/ios9-patch/js/angular/service/decorators/ios9-browser-fix.js我们还将补丁放在我们的 CDN 上。 我不建议使用 CDN 文件
对于生产,它只是在那里,所以现在更容易测试。请测试一下,让我们知道它是怎么回事,谢谢。
要测试它,请将此脚本标记放在您的角度或
ionic.bundle.js 文件:Also, right now it applies the patch whether you're running on iOS9 or
not. That will soon be fixed such that it runs only on the iOS 9 UIWebView.—
Reply to this email directly or view it on GitHub
https://github.com/angular/angular.js/issues/12241#issuecomment-139082474
.
我可以确认这个错误仍然存在于 iOS 9.1 Beta 1 中
我们经常使用$state.go
并且它仍然在状态之间闪烁/没有正确转换。
抱歉,该修复程序现在适用于我们的应用程序,唯一的问题是我们需要包含 https
CND 链接而不是 http CDN 看起来像 ios9 只允许 https 内部
应用程序,因此在使用 https 后,我们的应用程序工作正常。
https://code.ionicframework.com/patch/ios9-$browser-patch.js
2015 年 9 月 10 日星期四下午 3:22,Tyler Crammond通知@ github.com
写道:
我们经常使用 $state.go 并且它仍然在状态之间闪烁 / 不是
正确过渡。—
直接回复此邮件或在 GitHub 上查看
https://github.com/angular/angular.js/issues/12241#issuecomment -139189216
.
ios9-$browser-patch.js 也适用于我。 但它会产生一些 jshint 错误。 有没有办法为补丁做出贡献以帮助消除错误?
我不认为这个补丁是完全合理的,因为它不允许你从 Angular 外部更新位置。 对于大多数应用程序来说,这可能不是问题,但我们正在努力查看是否有更好的解决方案......
ios9-$browser-patch.js 对我不起作用。 当我从列表视图移动到详细视图时,我使用 $state.go() 在页面之间移动。 我第一次这样做时,它会滑过然后直接返回,然后我再次单击它就可以了。 UI-sref 按需要工作,但它不允许我做我需要做的条件逻辑。
不幸的是,下载补丁并存储它并从 ./lib/ 加载它(我检查了它是否已加载),对我来说没有任何改变:
Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []
http://errors.angularjs.org/1.3.13/$rootScope/infdig?p0=10&p1=%5B%5D
iOS 9 通用,离子 1.0.0。
Jorisw,尝试禁用ios9检测代码,看看它是否有效:
var isIOS9 = (navigator.userAgent.indexOf('Version/9.') != -1) && (navigator.appVersion.indexOf('9_0') != -1);
如果(!isIOS9){
// 如果不是 iOS9 UIWebView 不打补丁
返回 $browser;
}
@jyc66有效,谢谢。 我如何确保它不会破坏 iOS < 9 ?
isIOS9
方法有问题。 它应该检查:
> navigator.userAgent
< "Mozilla/5.0 (iPhone; CPU iPhone OS 9_0 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13A340 (2065230368)" = $1
> navigator.appVersion
< "5.0 (iPhone; CPU iPhone OS 9_0 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13A340 (2065230368)" = $2
是的,或者,您可以测试小于 9 的操作系统并在这些情况下禁用修复。 当前的检查将在即将推出的 iOS 9.1 上中断。
我现在正在这样做,直到我或有人想出更好的方法:
// only provide the patch for iOS9 on UIWebView
var isIOS9 = (navigator.userAgent.indexOf(' OS 9') != -1) && (navigator.appVersion.indexOf(' OS 9') != -1);
if (!isIOS9) {
// do not patch if not iOS9 UIWebView
return $browser;
}
嗯,这和我正在做的相似。
有谁知道如果/当 Apple 在更高版本的 iOS 中修复该问题时,将该补丁应用于 iOS 版本 >= 9.0 是否会导致问题?
@JeremyPlease我现在正在加载 9.1 测试版,我会检查一下
当我禁用用户代理检查时为我工作,将补丁作为缩小包的一部分提供。 这是一个非离子的、有角度的应用程序。 今晚晚些时候将进一步调查并确保一切按预期进行。
感谢 ionic 团队的付出!
所以 9.1beta one 还没有修复。 不惊讶。
这可能看起来很奇怪 - 但是有人看到在 iOS 9 上应用补丁时String.split() 函数无法正常工作https :
我很困惑! 在 iOS8.4 上运行良好,当然还有 Chrome。
更新:String.split 对我来说似乎不适用于 iOS 9 iPhone 6 和 6s 模拟器,与补丁无关。
顺便说一句 - 这是我用于用户代理检查的内容:
var isIOS9WebView = (navigator.userAgent.indexOf('Safari') === -1) && (navigator.appVersion.indexOf('OS 9') !== -1);
if (!isIOS9WebView) {
// do not patch if not iOS9 UIWebView
return $browser;
}
我相信最好的解决方案可能是在 Igor 的 pull request 中,但这对我有用,而不是在 iOS 9 Safari 上应用补丁,而只是在 UIWebView 上。
@dac09我想测试你的彗星,但我不知道要修改哪个文件...
你能告诉我必须修改哪个文件吗?
我正在使用@CleverCoder的补丁,这是 ionic 的补丁所基于的,没有限制它只能在 iOS9 UIWebView 中运行,并且它对 UIWebView iOS8、safari 或 Android 没有任何影响。
大家好,你能测试一下这个补丁吗: https :
它应该适用于 Angular 1.2 – 1.4.5 并且不需要任何 Angular 更新。 要点中提供了有关如何将其应用于您的应用程序的说明。
我们将在 1.4.6 中进行适当的修复,但与此同时,此独立补丁旨在简化修复的实施和部署,以便您可以快速推出。
嗨@IgorMinar - 我在 Angular 1.3 (Ionic beta-14) 部署中遇到以下错误。 我不认为 .decorator 方法在 1.3 的模块上可用?
未捕获的类型错误:angular.module(...).decorator 不是函数(匿名函数)@ angular-ios9-uiwebview.patch.js:33
@rajatrocks呃.. 好点。 module.decorator 只是 1.4 的特性。 让我换个补丁。
@rajatrocks我更新了要点
谢谢@IgorMinar ,现在“安装”很好。 将在 Ionic 线程上留下我的评论,因为它们与此更相关。
@IgorMinar我已包含您的 js 文件并在我的 app.js 中添加以下内容。 它不能解决我的问题。
@IgorMinar你的补丁并没有解决我的问题,而是从@mlynch的人做。
为了确保它只适用于 iOS 平台,我创建了一个简单的 Cordova 钩子:
https://gist.github.com/DURK/f2acd6bca4759e719801
更新:啊,我看到补丁现在包含一个检查,所以它只适用于 iOS9。
@IgorMinar跟进@DURK和@jprangenberg报告的内容,在 iPad Air 2 上进行测试时,“isIOS9UIWebView”功能似乎存在问题。如果我强制始终应用垫片,则补丁有效。
来自我的评论: https :
@IgorMinar ,您的补丁在 iOS 9 iPhone UIWebView 上运行良好,但 iPad 的用户代理检测存在一些问题。
UIWebView 中的 iOS 9 iPhone 用户代理:
Mozilla/5.0 (iPhone; CPU iPhone OS 9_0 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13A340
UIWebView 中的 iOS 9 iPad 用户代理:
Mozilla/5.0 (iPad; CPU OS 9_0 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13A340
将可靠地匹配所有这些的正则表达式是:
function isIOS9UIWebView(userAgent) {
return /(iPhone|iPad|iPod);.*OS 9_\d/.test(userAgent) && !/Version\/9\./.test(userAgent);
}
我已经分叉了@IgorMinar的要点并在此处进行了更改: https : //gist.github.com/JeremyPlease/72cb3bf98279fefed4e3
@DURK科尔多瓦挂钩不是必需的。 该补丁在不需要它的平台上不做任何事情。
@JeremyPlease iOS9 上的Safari 不受影响。 我们真的只想在 UIWebView 中应用补丁。
@JeremyPlease Safari iOS 9 不是问题,所以@IgorMinar的检查是正确的 - 我相信将其专门限制为 UIWebViews。
对我很有用。
我意识到这只是 UIWebView 中的一个问题,所以我更新了我的要点以在 Safari 中不适用:
function isIOS9UIWebView(userAgent) {
return /(iPhone|iPad|iPod);.*OS 9_\d/.test(userAgent) && !/Version\/9\./.test(userAgent);
}
我发布了补丁的v1.0.3
@IgorMinar如果您使用 ngRoute,此修复程序是否有效? 该修复程序对我不起作用...... :-(
@jprangenberg是的。 我的 ngroute 应用程序在 iphone/ipad 上运行良好。 你能提供更多细节吗? 还要确保您使用的是 v1.0.3+ 的补丁
@IgorMinar 1.0.3 版补丁在我的环境中正常工作。
索引.html:
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script src="lib/ngCordova/dist/ng-cordova.min.js"></script>
<script src="js/libs/angular-ios9-uiwebview.patch.js"></script>
应用程序.js:
angular.module('starter', [
'ionic',
'ngCordova',
'ngIOS9UIWebViewPatch',
'ionic.service.core',
'ionic.service.push',
'angular-loading-bar',
'starter.services',
'starter.controllers'
])
app.js(路由):
$stateProvider.state('app.regions', {
cache: false,
url: "/states/:state_id/regions",
views: {
'menuContent': {
templateUrl: "templates/regions.html",
controller: 'RegionsCtrl'
}
}
})
无法浏览应用程序。 如果您单击列表项,您会看到当前视图。 历史按钮改变。 如果单击历史记录按钮,您可以看到单击列表项的视图。
<ion-list>
<ion-item ng-repeat="state in states" href="#/app/states/{{state.id}}/regions">
{{state.name}}
</ion-item>
</ion-list>
@IgorMinar这对我不起作用。 有人有什么想法吗?
@jprangenberg您使用的是 Ionic 软件包的修补版本还是发行版?
@perrygovier我正在使用 @IgorMinar 的 1.0.3 版
@jprangenberg是的,但是 ionic.bundle.js。 那是什么版本?
我的 ionic.bundle.js 版本:
window.ionic.version = '1.0.0';
@perrygovier感谢您的帮助!
出于好奇,使用 1.1.0 版本的包有帮助吗?
http://code.ionicframework.com/1.1.0/js/ionic.bundle.min.js
您可能也需要更新的 CSS
http://code.ionicframework.com/1.1.0/css/ionic.min.css
嘿@jprangenberg ,虽然我们都在共同努力,但让我们继续就离子问题进行与离子相关的讨论,这样我们就不会向普通的 Angular 用户发送垃圾邮件driftyco/ionic#4082
所以这个错误在使用https://github.com/Telerik-Verified-Plugins/WKWebView时不会影响 WKWEBVIEW 吗?
该错误仅在 iOS 9 的 UIWebView 中。 使用 WKWebView 时不存在。
感谢您为这些人所做的工作,但不幸的是它对我不起作用。 我的动画损坏,页面根本无法加载,页面无法正确加载,基本上路由器完全不稳定。
我在 iPhone 6 上使用 Ionic bundle 1.1.0 和 iOS 9.1,以及https://code.ionicframework.com/patch/ios9-$browser-patch.js上的补丁文件。 我看到这样的错误:
错误:[$ rootScope:infdig ] 10 $digest() 迭代达到。 中止!
在最后 5 次迭代中触发的观察者:[]
有什么建议么?
谢谢!
@scotopolis你有没有尝试过 Igor 的补丁: https : //gist.github.com/IgorMinar/863acd413e3925bf282c
@petebacondarwin谢谢,Igor 的补丁对我
此处的一些测试和来自@IgorMinar的补丁导致后退按钮动画和控制器出现问题。 我看到了屏幕的控制器,当我单击返回时,我正在退出重新创建。 这导致动画在该视图中运行,因为它被导航出屏幕,各种奇怪。
到目前为止,我在使用 ionic 的 nightly 时没有看到任何问题,但更新了 iOS9 检测。
var userAgent = navigator.userAgent,
isIOS9 = /(iPhone|iPad|iPod).* OS 9_\d/.test(userAgent) && !/Version\/9\./.test(userAgent);
我刚刚推送了补丁的 v1.1.0: https :
与 ionic 团队一起,我们不再能够使用此版本的补丁重现任何闪烁。
请升级,如果您发现更多问题,请告诉我们。 (还要确保除了补丁的 v1.1.0 之外,您没有使用任何其他补丁来解决此问题)。
我们将在下周在 master 中进行修复,以便不再需要修补 Angular v1.4.6。
这个新版本的补丁非常适合我。 谢谢@IgorMinar!
发布的 1.4.6 是否永久修复了这个问题?
@alexislg2 - 是的,这个版本应该可以解决这个问题,所以你不需要应用补丁。
确认,适用于我的模拟器和设备,只需要我的用户等待苹果批准 2 周;-(
@dbroadhurst我听说您可以引用https://openradar.appspot.com/22186109错误报告来快速跟踪您对应用程序的更新。
您可以关注此 WebKit 错误以获取更新。
嗨,您似乎已经解决了 Angular.js 上散列更改的 iOS9 异步调用问题。
我进行了研究,也发布在 stackoverflow 上,但到目前为止我发现的唯一解决方案是在您的 angular browser.js 补丁中。
我对 angular 不太熟悉,我想了解您做了什么让您修复了
每个基于哈希路由的 Web 应用程序
您能解释一下您是如何识别和解决问题的吗?
@lchenneberg - 解决 AngularJS 问题的提交在这里https://github.com/angular/angular.js/commit/8d39bd8abf423517b5bff70137c2a29e32bff76d
问题是这个特定的浏览器在 JavaScript 事件循环的下一次运行之前不会更新window.location.href
的值。 这意味着,如果您写入该值,然后立即将其读回,您会得到一个不同的值:
console.log(window.location.href) // -> http://my.domain.com/path/to/page
window.location.href = 'http://my.domain.com/path/to/other/page';
console.log(window.location.href) // -> http://my.domain.com/path/to/page
// next tick of the event loop
console.log(window.location.href) // -> http://my.domain.com/path/to/other/page
请注意,第二个console.log
返回旧值,而不是新值。 当前事件循环完成后,更新值,如第三个console.log
我们提出的解决方法是缓存我们写的值,如果浏览器没有同步更新,然后从那时起使用该值,而不是从window.location.href
返回的值,直到有一个hashchange
事件,它告诉我们浏览器终于自己解决了。
希望有帮助。
@IgorMinar的补丁对我来说效果很好。 我正在使用以下版本的 Angular 和 Ionic:
window.ionic.version "1.0.1"
angular.version
Object {full: "1.3.13", major: 1, minor: 3, dot: 13, codeName: "meticulous-riffleshuffle"}
@IgorMinar的补丁也对我们
但我还有一个问题,你们中的一个人也许可以回答:
启动添加到 iPad 主屏幕的网页是否使用 UIWebView 或 WKWebView 打开页面?
或者,更重要的是,以这种方式访问 Web 应用程序是否利用了 Nitro 渲染引擎?
@tpeiffer他们会使用 wkwebview,因为它只是没有地址栏的 safari。
嗨,我对旧版本的 angular 有同样的问题:1.0.6
我看到所有修复都是针对较新版本的,您知道我应该在哪里查看是否可以解决此问题吗? 谢谢。
@tzamora你试过应用@IgorMinar的补丁吗? 也许 1.0.6 还为时过早。
@petebacondarwin @IgorMinar的补丁引用了一个名为 browser.js 的文件。 我没有任何名为 browser.js 的文件
仅供参考,前几天在 WebKit 中修复了潜在问题:
http://trac.webkit.org/changeset/190092
http://trac.webkit.org/changeset/190100
我在 js 补丁中得到了这个,但不是马上。 这个(angularjs 和 Ionic)的新手,所以如果有人可以检查这个并让我知道我是否错过了任何重要的东西,我真的很感激! (例如,平台对象效率很低等)
笔记:
function isIOS9UIWebView(userAgent) {
return (/9\.[0-9]\.[0-9]/.test(ionic.Platform.version()) && /iOS/.test(ionic.Platform.device() ));
//return true;
//return (navigator.userAgent.indexOf(' OS 9') != -1) && (navigator.appVersion.indexOf(' OS 9') != -1);
//return /(iPhone|iPad|iPod).* OS 9_\d/.test(userAgent) && !/Version\/9\./.test(userAgent);
// only provide the patch for iOS9 on UIWebView
}
我在模拟器上的 8.4 上遇到了这个问题; 所以我认为它不仅限于 iOS 9。我刚刚更新了代理字符串检查以包含 iOS 8 和 9 版本。这是代理字符串。
“Mozilla/5.0(iPhone;CPU iPhone OS 8_4,如 Mac OS X)AppleWebKit/600.1.4(KHTML,如 Gecko)Mobile/12H141(140307121489296)”
+1
你好
有人可以确认这是否在 ios 9.2 上解决了吗? (测试版)
谢谢 :)
我无法在今天早上更新到 iPhone 6 上的 iOS 9.2 (13C75) 时复制该问题。到目前为止看起来不错。 这个错误仍然是开放的 - https://openradar.appspot.com/22186109
如果应用此补丁,是否会对 iOS 9.2 及更高版本产生负面影响? 我将使用我们自己的应用程序对此进行测试,但我想确保我不会引入在测试我们的特定情况时未显示的问题。
据我所知,所有补丁都使用一个正则表达式来过滤 iOS 9 及更高版本,但不是专门用于 9.x 和 9.1 的过滤器。
嘿伙计们,这个问题目前发生在带有 iOS 9 的 iPhone 6 中,谁能告诉我为什么?
https://forum.ionicframework.com/t/ios-9-beta-slide-menu-app-transition-issue/30768
是我需要应用的另一个补丁吗? 请让我知道,我真的需要解决那个屏幕重叠问题。
更新到 iOS 9.2 似乎也为我解决了这个问题。
@bruno-serfe 这是一个关于 iOS 如何处理window.location
,它只存在于 iOS 9.0.x 中。 如果您可以更新到 Angular 1.4.6+,那么您无需执行任何其他操作,因为此版本包含修复程序。 如果您无法升级,则https://github.com/angular/angular.js/issues/12241#issuecomment -139446288 上的补丁具有相同的修复。
如前所述,此问题仅存在于 iOS 9.0.x 中,因为此问题已在 iOS 9.1.0 中修复。
发布在 ionic 上的问题看起来是同一个问题,所以同样的修复应该是双向的。
@lgalfaso感谢您的回复,我将尝试修复我发现的摘要错误,如果这不能解决问题,我将尝试升级 angular,感谢您的回复!。
谢谢@lgalfaso :+1:
当我将 web 应用程序添加到主屏幕并将其作为独立使用时,我遇到了这个问题,但是从 AngularJS 1.4.5 升级到 1.5 完全解决了这个问题,并且加速了导航!
@volgwfang您
最有用的评论
在这一点上更进一步。 我在 Angular 中对位置进行了更改。
在“更新浏览器”部分,我将 $rootScope.$evalAsync 更改为 $rootScope.$applyAsync。
这两种方法看起来完全一样。 在您查看实际的 $digest 执行之前,差异不会变得明显。 当 AngularJS 执行摘要时,它会遍历 Scope 树并执行 $watch() 绑定,直到不再产生脏数据。 在这个生命周期中,$applyAsync() 队列和 $evalAsync() 队列都会被刷新; 但是,这发生在两个非常不同的地方。
$applyAsync() 队列只会在 AngularJS 开始检查脏数据之前在 $digest 的顶部刷新。 因此,$applyAsync() 队列将在 $digest 期间最多被刷新一次,并且只有在 $digest 开始之前队列已经被填充时才会被刷新。
另一方面,$evalAsync() 队列在实现 $digest 内部“脏检查”的 while 循环的顶部刷新。 这意味着在摘要期间添加到 $evalAsync() 队列的任何表达式都将在同一摘要中稍后执行。
为了使这种差异更加具体,这意味着 $evalAsync() 从 $watch() 绑定中添加的异步表达式将在相同的摘要中执行。 $applyAsync() 从 $watch() 绑定中添加的异步表达式将在稍后的时间点(~10ms)执行。
希望这已经对你们中的一些人有所帮助:-)。