Javascript 检测设备是否为iOS

Javascript 检测设备是否为iOS,javascript,ios,browser,browser-feature-detection,Javascript,Ios,Browser,Browser Feature Detection,我想知道是否可以检测浏览器是否在iOS上运行,类似于使用Modernizr进行功能检测(尽管这显然是设备检测而不是功能检测) 通常情况下,我会倾向于功能检测,但我需要找出一台设备是否是iOS,因为根据这个问题,iOS设备上的用户代理会说其中有iPhone或iPad。我只是根据这些关键字进行筛选。检测iOS 对于和,下面的所有答案现在都需要考虑到这一点 这可能是涵盖iOS 13的最短备选方案: function iOS() { return [ 'iPad Simulator',

我想知道是否可以检测浏览器是否在iOS上运行,类似于使用Modernizr进行功能检测(尽管这显然是设备检测而不是功能检测)


通常情况下,我会倾向于功能检测,但我需要找出一台设备是否是iOS,因为根据这个问题,iOS设备上的用户代理会说其中有iPhone或iPad。我只是根据这些关键字进行筛选。

检测iOS 对于和,下面的所有答案现在都需要考虑到这一点

这可能是涵盖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版本 检测iOS版本最常用的方法是通过。但也存在特征检测推理

我们知道,
historyapi
是在iOS4-
matchmediaapi
的iOS5-
webaudioapi
的iOS6-
webspeechapi
的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';
}
函数iOSversion(){

如果(iOS){/为了检测iOS版本,必须使用如下Javascript代码对用户代理进行解构:

 var res = navigator.userAgent.match(/; CPU.*OS (\d_\d)/);
    if(res) {
        var strVer = res[res.length-1];
        strVer = strVer.replace("_", ".");
        version = strVer * 1;
    }

我几年前写过这篇文章,但我相信它仍然有效:

if(navigator.vendor != null && navigator.vendor.match(/Apple Computer, Inc./) && navigator.userAgent.match(/iPhone/i) || (navigator.userAgent.match(/iPod/i))) 

    {

        alert("Ipod or Iphone");

    }

else if (navigator.vendor != null && navigator.vendor.match(/Apple Computer, Inc./) && navigator.userAgent.match(/iPad/i))  

    {

        alert("Ipad");

    }

else if (navigator.vendor != null && navigator.vendor.match(/Apple Computer, Inc./) && navigator.userAgent.indexOf('Safari') != -1)

    {

        alert("Safari");

    }

else if (navigator.vendor == null || navigator.vendor != null)

    {

        alert("Not Apple Based Browser");

    }
var isiOSSafari=(navigator.userAgent.match(/像Mac OS X/i))?true:false;

如果您正在使用,可以为其添加自定义测试

无论您决定使用哪种检测模式(userAgent、navigator.vendor或navigator.platform),您都可以将其打包,以便以后更方便地使用

//添加现代化测试
modernizer.addTest('isios',function(){
返回navigator.userAgent.match(/(iPad | iPhone | iPod)/g);
});
//用法
如果(使isios现代化){
//这会将ios类添加到body中
modernizer.前缀为('ios');
}否则{
//这会将notios类添加到body中
modernizer.前缀为('notios');
}

这将变量
\u iOSDevice
设置为truefalse

_iOSDevice = !!navigator.platform.match(/iPhone|iPod|iPad/);

简化的、易于扩展的版本

var iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;

如果可能的话,在添加Modernizer测试时,你应该为一个功能添加一个测试,而不是一个设备或操作系统。如果需要的话,为iPhone添加十个测试并没有什么错。有些东西就是无法检测到功能

    Modernizr.addTest('inpagevideo', function ()
    {
        return navigator.userAgent.match(/(iPhone|iPod)/g) ? false : true;
    });
例如,在iPhone(不是iPad)上,视频不能在网页上内联播放,它会打开全屏。因此我创建了一个测试“无页面视频”

然后,您可以在css中使用它(Modernizer会添加一个类
。如果测试失败,则不会在
标记中添加inpagevideo


这将隐藏iPhone上的视频(在本例中,我实际做的是用鼠标单击显示另一个图像来播放视频-我只是不想显示默认的视频播放器和播放按钮)。

更新:我的原始答案不包括桌面模式下的iPad
(在即将推出的iPadOS 13及更高版本中,默认更改为桌面模式)。
这对于我的用例很好,如果不适合您,请使用以下更新:

// iPhone and iPad including iPadOS 13+ regardless of desktop mode settings

iOSiPadOS = /^iP/.test(navigator.platform) ||
           /^Mac/.test(navigator.platform) && navigator.maxTouchPoints > 4;
  • 只要
    • 台式机Mac根本不支持触摸事件
    • 或不超过4个触点(当前iOS设备支持5个触点)
  • 它很快,因为regexp
    ^
    首先检查平台字符串的起始位置,如果没有“iP”则停止(比搜索长UA字符串直到结束都要快)

  • 它比
    navigator更安全。用户代理
    作为
    navigator检查。平台
    不太可能伪造
  • 检测iPhone/iPad模拟器

原始答案:
哇,这里有很多复杂的代码。请保持简单! 这是一款快速、省电且工作良好的产品:

 iOS = /^iP/.test(navigator.platform);

  // or, if you prefer it verbose:
 iOS = /^(iPhone|iPad|iPod)/.test(navigator.platform);

使用更实用的方法稍微更新第一个答案

const-isIOS=[
“iPad模拟器”,
“iPhone模拟器”,
“iPod模拟器”,
“iPad”,
“iPhone”,
“iPod”,
].indexOf(navigator.platform)!=-1;

运行iOS 13的iPad将有
导航器。platform
设置为
MacIntel
,这意味着您需要找到另一种方法来检测iPadOS设备。

在iOS 13之后,您应该检测这样的iOS设备,因为iPad将不会被旧方法检测为iOS设备(由于新的“桌面”)选项(默认情况下启用):

iOS<13或禁用桌面模式的iPhone或iPad的第一个条件,默认配置中iPadOS 13的第二个条件,因为它的定位类似于Macintosh Intel,但实际上是唯一具有多点触摸功能的Macintosh

与其说是一个真正的解决方案,不如说是一个黑客,但工作是相关的
 iOS = /^iP/.test(navigator.platform);

  // or, if you prefer it verbose:
 iOS = /^(iPhone|iPad|iPod)/.test(navigator.platform);
let isIOS = /iPad|iPhone|iPod/.test(navigator.platform)
|| (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)
let isIOS = (/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&
!window.MSStream
var mql = window.matchMedia("(orientation: landscape)");

/**
 * If we are in landscape but the height is bigger than width
 */
if(mql.matches && window.screen.height > window.screen.width) {
    // IOS
} else {
    // Mac OS
}
  const isApple = ['iPhone', 'iPad', 'iPod', 'iPad Simulator', 'iPhone Simulator', 'iPod Simulator',].includes(navigator.platform)
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()));
})();
const iOS_1to12 = /iPad|iPhone|iPod/.test(navigator.platform);

const iOS13_iPad = (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1));

const iOS1to12quirk = function() {
  var audio = new Audio(); // temporary Audio object
  audio.volume = 0.5; // has no effect on iOS <= 12
  return audio.volume === 1;
};

const isIOS = !window.MSStream && (iOS_1to12 || iOS13_iPad || iOS1to12quirk());