检测设备是否为iOS

Spa*_*awk 378 javascript browser ios browser-feature-detection

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

通常我更喜欢功能检测,但我需要找出一个设备是否是iOS,因为他们根据这个问题处理视频的方式YouTube API无法使用iPad/iPhone /非Flash设备

Pie*_*rre 765

检测iOS

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

var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
Run Code Online (Sandbox Code Playgroud)

另一种方式是依靠navigator.platform:

var iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
Run Code Online (Sandbox Code Playgroud)

iOS将是truefalse

为什么不用MSStream

微软在IE11中注入了iPhone这个词userAgent,试图以某种方式欺骗Gmail.因此我们需要排除它.更多关于这里这里的信息.

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

Mozilla/5.0(移动; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0;诺基亚; Lumia 930),如iPhone OS 7_0_3 Mac OS X AppleWebKit/537(KHTML,如Gecko)移动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;
}
Run Code Online (Sandbox Code Playgroud)

iOS()将是truefalse

注意:无论navigator.userAgent并且navigator.platform可以由用户或浏览器扩展伪造.


检测iOS版本

检测iOS版本的最常用方法是从用户代理字符串中解析它.但也有特征检测推断* ;

我们知道iOS4history API引入的一个事实- 在iOS5中 - 在iOS6中 - 在iOS7引入,等等.matchMedia APIwebAudio APIWebSpeech 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';
}
Run Code Online (Sandbox Code Playgroud)

  • 这是编写支票的更好方法:`var iOS = /(iPad | iPhone | iPod)/g.test(navigator.userAgent);` (23认同)
  • 您在第二个片段中所做的是功能推断,而不是功能检测.功能检测是测试您实际将要使用的功能,而您正在做的是测试您在特定版本的操作系统中引入的功能,并从中推断操作系统版本.这很脆弱,因为iOS的未来版本可能会删除这些功能. (8认同)
  • 只是注意 - navigator.platform数组在iPad模拟器上不起作用,因为它在平台字符串中有整个短语"iPad Simulator". (4认同)
  • 从iOS 13开始,iPad的用户代理已更改为“ Mac OS”,例如:`Mozilla / 5.0(Macintosh; Intel Mac OS X 10_15)AppleWebKit / 605.1.15(KHTML,like Gecko)Version / 13.0 Safari / 605.1.15 `所以这个答案需要更新 (4认同)
  • 如果用户使用的是 Window Phone,则在用户代理字符串中测试 iPad、iPhone 或 iPod 将给出误报。此设备上的 Internet Explorer 在用户代理字符串中包含一条消息“...like iPhone OS...”,因此在此测试中将返回 true。 (3认同)
  • `navigator.platform` 现已弃用,因此我正在寻找替代技术,但无济于事。https://developer.mozilla.org/en-US/docs/Web/API/Navigator/platform (3认同)
  • 谢谢皮埃尔 - 这段代码看起来更简单,我只是想知道我是否可以指定'iOS'而不必输入所有单独的iDevices .... if((navigator.userAgent.match(/ iPhone/i))| |(navigator.userAgent.match(/ iPod/i))||(navigator.userAgent.match(/ iPad/i))){//做点什么} (2认同)
  • `document.write("浏览器版本:"+ navigator.appVersion)`这是浏览器版本而不是iOS版本. (2认同)
  • 最简单的答案:var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent); (2认同)
  • 这里和 StackOverflow 页面上其他地方推荐的“(navigator.userAgent.includes("Mac") && "ontouchend" in document)` 已经不够了,因为它在非触摸设备上的 Chrome 85 上返回 true。目前看来,添加 `&& navigator.maxTouchPoints > 2` 似乎是一个足够好的权宜之计。 (2认同)

Vit*_*.us 14

这会将变量设置_iOSDevicetruefalse

_iOSDevice = !!navigator.platform.match(/iPhone|iPod|iPad/);
Run Code Online (Sandbox Code Playgroud)

  • @astronought 砰砰,你是布尔人 :D (4认同)
  • 使用 `/iPhone|iPod|iPad/.test(navigator.platform)` 你可以避免 `!!` (4认同)
  • @astronought双重否定用于转换为布尔值 (3认同)
  • 什么!做? (2认同)

Thi*_*PXP 10

如果您使用的是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');
}
Run Code Online (Sandbox Code Playgroud)

  • 只是很小的注意:你可以简化`return x?true:false` to`返回Boolean(x)`或只返回`return !! x` (3认同)
  • 小心,Modernizr自动小写添加的测试的名称.(在你的例子中,Modernizr.isiOS永远不会返回true).我认为lib的行为不好...... (2认同)

kik*_*ora 10

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

let isIOS = /iPad|iPhone|iPod/.test(navigator.platform)
|| (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)
Run Code Online (Sandbox Code Playgroud)

对于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
Run Code Online (Sandbox Code Playgroud)

  • @PaulC,您是正确的,因为 iOS 12 及以下版本未定义 maxTouchPoints,但 kikiwora 走在正确的轨道上,因为 iOS 13 支持 maxTouchPoints。请参阅我的答案。 (2认同)

Bob*_*lof 10

这里以前的答案都不适用于所有版本的 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()));
})();
Run Code Online (Sandbox Code Playgroud)

请注意,此代码片段的编写优先考虑可读性,而不是简洁性或性能。

解释:

  • 如果用户代理包含任何“iPod|iPhone|iPad”,那么显然该设备是 iOS。否则,继续...

  • 不包含“Macintosh”的任何其他用户代理都不是 Apple 设备,因此不能是 iOS。否则,它是苹果设备,所以继续......

  • 如果maxTouchPoints值为1或更大,则 Apple 设备具有触摸屏,因此必须是 iOS,因为没有带触摸屏的 Mac(感谢 kikiwora 提及maxTouchPoints)。请注意,这maxTouchPointsundefined针对 iOS 12 及更低版本的,因此我们需要针对该场景使用不同的解决方案...

  • iOS 12 及以下版本有一个在 Mac OS 中不存在的怪癖。奇怪的是,元素的volume属性Audio不能成功设置为除1. 这是因为 Apple 不允许在AudioiOS 设备的元素上更改音量,但在 Mac OS上允许。这种怪癖可以用作区分 iOS 设备和 Mac OS 设备的最终后备方法。

  • @Tspoon,提供的代码片段创建了一个一次性的“Audio”元素(如果需要)。在这种情况下,该元素实际上并不用于播放声音,并且它不会影响您可能在系统中使用的其他“音频”元素的音量。 (2认同)

小智 8

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


Sim*_* B. 6

检测 iOS(<12 和 13+)

社区维基,正如编辑队列所说,它已满,所有其他答案目前都已过时或不完整。

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());
Run Code Online (Sandbox Code Playgroud)


小智 5

简化,易于扩展的版本。

var iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;
Run Code Online (Sandbox Code Playgroud)


j.j*_*.j. 5

更新:我的原始答案不包括桌面模式下的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;
Run Code Online (Sandbox Code Playgroud)
  • 这应该是安全的,只要
    • 桌面 Mac 根本不支持触摸事件
    • 或不超过 4 个触点(当前 iOS 设备支持 5 个触点)
  • 它很快,因为正则表达式^首先检查平台字符串的起始位置,如果没有“iP”就停止(无论如何都比搜索长 UA 字符串直到结束要快)
  • navigator.userAgent检查更安全,因为navigator.platform伪造的可能性要小得多
  • 检测 iPhone / iPad 模拟器

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

恕我直言,这是一种快速、保存且运行良好的方法:

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

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