我想知道是否有可能检测浏览器是否在 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 不允许在Audio
iOS 设备的元素上更改音量,但在 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');
}