检测设备是否为iOS

时间:2012-01-27 19:02:05

标签: javascript ios browser browser-feature-detection

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

通常情况下我会支持功能检测,但是我需要找出设备是否是iOS,因为他们根据这个问题处理视频的方式YouTube API not working with iPad / iPhone / non-Flash device

19 个答案:

答案 0 :(得分:709)

检测iOS

我不是用户代理嗅探的粉丝,但是你会这样做:

var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;

另一种方法是依靠navigator.platform

var iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);

iOS可以是truefalse

为什么不是MSStream

微软在IE11的userAgent中注入了 iPhone 这个词,试图以某种方式欺骗Gmail。因此我们需要排除它。有关此herehere的详细信息。

以下是IE11更新的userAgent(适用于Windows Phone 8.1更新的Internet Explorer):

  

Mozilla / 5.0(移动版; Windows Phone 8.1; Android 4.0; ARM; Trident / 7.0;   触摸; RV:11.0; IEMobile / 11.0;诺基亚; Lumia 930)喜欢iPhone OS 7_0_3   Mac OS X AppleWebKit / 537(KHTML,如Gecko)Mobile Safari / 537


轻松添加更多设备,而不使用正则表达式:

function iOS() {

  var iDevices = [
    'iPad Simulator',
    'iPhone Simulator',
    'iPod Simulator',
    'iPad',
    'iPhone',
    'iPod'
  ];

  if (!!navigator.platform) {
    while (iDevices.length) {
      if (navigator.platform === iDevices.pop()){ return true; }
    }
  }

  return false;
}

iOS()可以是truefalse

注意navigator.userAgentnavigator.platform都可以由用户或浏览器扩展程序伪造。


检测iOS版本

检测iOS版本的最常用方法是parsing it from the User Agent string。但是还有功能 detection 推断 *;

我们知道{em> iOS4 中引入history API的事实 - iOS5 中的matchMedia API - 中的webAudio API iOS6 - iOS7 中的WebSpeech API等等..

注意:以下代码不可靠,如果在较新的iOS版本中弃用这些HTML5功能,则会破坏以下代码。你被警告了!

function iOSversion() {

  if (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) {
    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';
}

答案 1 :(得分:12)

这会将变量_iOSDevice设置为 true false

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

答案 2 :(得分:11)

在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。 / p>

不是真正的解决方案,而是hack,但是对我来说可靠地工作

PS 。如前所述,您可能应该添加IE检查

let isIOS = (/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&
!window.MSStream

答案 3 :(得分:9)

如果您使用的是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');
}

答案 4 :(得分:8)

有这种自定义Modernizr测试:https://gist.github.com/855078

答案 5 :(得分:7)

以上所有答案均不适用于所有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。否则,它是一台Apple设备,因此继续...

  • 如果maxTouchPoints的值为1或更大,则Apple设备具有触摸屏,因此必须为iOS,因为没有Macs带有触摸屏(对kikiwora表示感谢) maxTouchPoints)。请注意,maxTouchPoints是iOS 12及更低版本的undefined,因此我们需要针对该情况的其他解决方案...

  • iOS 12和更低版本的Mac OS中没有这个怪癖。奇怪的是,volume元素的Audio属性无法成功设置为1以外的任何值。这是因为Apple不允许iOS设备的Audio元素上的音量更改,但Mac OS则允许。该怪癖可以用作区分iOS设备和Mac OS设备的最终后备方法。

答案 6 :(得分:3)

iOS设备上的用户代理说iPhone或iPad。我只是根据这些关键字进行过滤。

答案 7 :(得分:3)

简化,易于扩展的版本。

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

答案 8 :(得分:2)

在添加Modernizr测试时,您应该尽可能为功能添加测试,而不是设备或操作系统。如果需要的话,添加10个测试所有iPhone的测试都没有错。有些事情不能被检测到。

    Modernizr.addTest('inpagevideo', function ()
    {
        return navigator.userAgent.match(/(iPhone|iPod)/g) ? false : true;
    });

例如,在iPhone(不是iPad)上无法在网页上内嵌播放视频,它会全屏显示。所以我创建了一个测试&#39; no-inpage-video&#39;

然后您可以在css中使用它(如果测试失败,Modernizr会向.no-inpagevideo标记添加一个类<html>

.no-inpagevideo video.product-video 
{
     display: none;
}

这会隐藏iPhone上的视频(在这种情况下我实际上正在做的是显示带有onclick播放视频的替代图像 - 我只是不想要默认的视频播放器和播放按钮显示)。

答案 9 :(得分:2)

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

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");

    }

答案 10 :(得分:1)

哇,这里有很多冗长的棘手代码。请保持简单!

这是恕我直言,快速,保存并且运行良好:

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

 // or, more future-proof (in theory, probably not in practice):

 iOS = /^iP(hone|[ao]d)/.test(navigator.platform);

 // or, if you prefer readability:

 iOS = /^(iPhone|iPad|iPod)/.test(navigator.platform);
  • 之所以快,是因为regexp首先检查平台字符串的 ^ s 放置位置,如果没有“ iP”则停止(比搜索长的UA字符串要快得多,直到结束为止)
  • 比UA检查更安全(假设navigator.platform不太可能被伪造)
  • 检测iPhone / iPad模拟器

答案 11 :(得分:1)

检测iOS(<12和13 +)

社区Wiki,因为编辑队列说它已满,而所有其他答案目前已过时或不完整。

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());

答案 12 :(得分:0)

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

    const isIOS = [
      'iPad Simulator',
      'iPhone Simulator',
      'iPod Simulator',
      'iPad',
      'iPhone',
      'iPod',
    ]
      .map(device => navigator.platform === device)
      .filter(device => device)
      .reduce(() => true, false);

答案 13 :(得分:0)

可能值得回答的是,运行iOS 13的iPad将navigator.platform设置为MacIntel,这意味着您需要找到另一种检测iPadOS设备的方法。

答案 14 :(得分:0)

您也可以使用includes

  const isApple = ['iPhone', 'iPad', 'iPod', 'iPad Simulator', 'iPhone Simulator', 'iPod Simulator',].includes(navigator.platform)

答案 15 :(得分:0)

无需测试 navigator.userAgentnavigator.platform

const isIOS = typeof navigator.standalone === 'boolean';

navigator.standalone 仅在 iOS Safari 上设置。见MDNSafari HTML Reference

答案 16 :(得分:-1)

在我的情况下,用户代理还不够好,因为在Ipad中用户代理与Mac OS中的用户代理相同,因此我不得不做一个讨厌的把戏:

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
}

答案 17 :(得分:-2)

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

答案 18 :(得分:-2)

为了检测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;
    }