我想知道是否有可能检测浏览器是否在 iOS 上运行,类似于使用 Modernizr 进行功能检测的方式(尽管这显然是设备检测而不是功能检测)。
通常我更喜欢功能检测,但我需要找出设备是否是 iOS,因为它们按照这个问题处理视频的方式YouTube API 不适用于 iPad / iPhone / 非 Flash 设备
我想知道是否有可能检测浏览器是否在 iOS 上运行,类似于使用 Modernizr 进行功能检测的方式(尽管这显然是设备检测而不是功能检测)。
通常我更喜欢功能检测,但我需要找出设备是否是 iOS,因为它们按照这个问题处理视频的方式YouTube API 不适用于 iPad / iPhone / 非 Flash 设备
在iOS 13 iPad 中,用户代理和平台字符串都发生了变化,似乎可以区分 iPad 和 MacOS,因此下面的所有答案现在都需要考虑到这一点。
这可能是涵盖 iOS 13 的最短替代方案:
function iOS() {
return [
'iPad Simulator',
'iPhone Simulator',
'iPod Simulator',
'iPad',
'iPhone',
'iPod'
].includes(navigator.platform)
// iPad on iOS 13 detection
|| (navigator.userAgent.includes("Mac") && "ontouchend" in document)
}
iOS将是true或false
用户代理嗅探更危险,问题经常出现。
在 iPad iOS 13 上,用户代理与 MacOS 13 计算机的用户代理相同,但如果您忽略 iPad,这可能仍然有效一段时间:
var iOS = !window.MSStream && /iPad|iPhone|iPod/.test(navigator.userAgent); // fails on iPad iOS 13
这!window.MSStream是为了不错误地检测 IE11,请参阅此处和此处。
注意:无论navigator.userAgent并且navigator.platform可以由用户或浏览器扩展伪造。
存在用于更改 userAgent 或平台的浏览器扩展,因为网站使用过于严厉的检测并且经常禁用某些功能,即使用户的浏览器本来可以使用该功能。
为了缓和与用户的这种冲突,建议针对每种情况专门检测您的网站需要的确切功能。然后,当用户获得具有所需功能的浏览器时,它已经可以工作而无需更改额外的代码。
检测 iOS 版本的最常见方法是从 User Agent string 解析它。但也有特征检测推断* ;
我们知道history API在iOS4 -matchMedia API在iOS5 -webAudio API在iOS6 -WebSpeech API在iOS7等中引入的事实。
注意:以下代码不可靠,如果这些 HTML5 功能中的任何一个在较新的 iOS 版本中被弃用,则会中断。你被警告了!
function iOSversion() {
if (iOS) { // <-- Use the one here above
if (window.indexedDB) { return 'iOS 8 and up'; }
if (window.SpeechSynthesisUtterance) { return 'iOS 7'; }
if (window.webkitAudioContext) { return 'iOS 6'; }
if (window.matchMedia) { return 'iOS 5'; }
if (window.history && 'pushState' in window.history) { return 'iOS 4'; }
return 'iOS 3 or earlier';
}
return 'Not an iOS device';
}
在 iOS 13 之后,您应该像这样检测 iOS 设备,因为旧的方式不会将 iPad 检测为 iOS 设备(由于新的“桌面”选项,默认情况下启用):
let isIOS = /iPad|iPhone|iPod/.test(navigator.platform)
|| (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)
iOS < 13 或 iPhone 或 iPad 禁用桌面模式的第一个条件,默认配置下 iPadOS 13 的第二个条件,因为它的定位类似于 Macintosh Intel,但实际上是唯一具有多点触控的 Macintosh。
与其说是一个真正的解决方案,不如说是一个黑客,但对我来说可靠地工作
PS如前所述,您可能应该添加 IE 检查
let isIOS = (/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&
!window.MSStream
这将变量设置_iOSDevice为true或false
_iOSDevice = !!navigator.platform.match(/iPhone|iPod|iPad/);
这里以前的答案都不适用于所有版本的 iOS 上的所有主要浏览器,包括 iOS 13。这是一个适用于所有 iOS 版本的 Safari、Chrome 和 Firefox 的解决方案:
var isIOS = (function () {
var iosQuirkPresent = function () {
var audio = new Audio();
audio.volume = 0.5;
return audio.volume === 1; // volume cannot be changed from "1" on iOS 12 and below
};
var isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
var isAppleDevice = navigator.userAgent.includes('Macintosh');
var isTouchScreen = navigator.maxTouchPoints >= 1; // true for iOS 13 (and hopefully beyond)
return isIOS || (isAppleDevice && (isTouchScreen || iosQuirkPresent()));
})();
请注意,此代码片段的编写优先考虑可读性,而不是简洁性或性能。
解释:
如果用户代理包含“iPod|iPhone|iPad”中的任何一个,那么显然该设备是 iOS。否则,继续...
不包含“Macintosh”的任何其他用户代理都不是 Apple 设备,因此不能是 iOS。否则,它是苹果设备,所以继续......
如果maxTouchPoints值为1或更大,则 Apple 设备具有触摸屏,因此必须是 iOS 设备,因为没有带触摸屏的 Mac(感谢 kikiwora 提及maxTouchPoints)。请注意,这maxTouchPoints是undefined针对 iOS 12 及更低版本的,因此我们需要针对该场景使用不同的解决方案...
iOS 12 及以下版本有一个在 Mac OS 中不存在的怪癖。奇怪的是,元素的volume属性Audio不能成功设置为除1. 这是因为 Apple 不允许在AudioiOS 设备的元素上更改音量,但在 Mac OS上允许。这种怪癖可以用作区分 iOS 设备和 Mac OS 设备的最终后备方法。
如果您使用的是Modernizr,则可以为其添加自定义测试。
无论您决定使用哪种检测模式(userAgent、navigator.vendor 或 navigator.platform),您都可以将其包装起来以便以后使用。
//Add Modernizr test
Modernizr.addTest('isios', function() {
return navigator.userAgent.match(/(iPad|iPhone|iPod)/g);
});
//usage
if (Modernizr.isios) {
//this adds ios class to body
Modernizr.prefixed('ios');
} else {
//this adds notios class to body
Modernizr.prefixed('notios');
}