检测设备是否为iOS

2020/09/27 23:01 · javascript ·  · 0评论

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

通常,我宁愿使用功能检测,但我需要根据该问题确定设备是否为iOS,因为它们处理视频的方式YouTube API无法在iPad / iPhone /非Flash设备上使用

检测iOS

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将是truefalse

更糟糕的选择:用户代理嗅探

用户代理嗅探更加危险,并且经常出现问题。

在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版本的最常见方法是通过User Agent字符串进行解析但是也有特征检测推论* ;

我们知道,一个事实,history API在引进的iOS4 - matchMedia APIiOS5中 - webAudio APIiOS6的 - WebSpeech APIiOS7等。

注意:以下代码不可靠,如果在更新的iOS版本中不赞成使用这些HTML5功能中的任何功能,则这些代码将中断。你被警告了!

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

这会将变量设置_iOSDevicetruefalse

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

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

简化,易于扩展的版本。

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

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

这里的先前答案均不适用于所有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适用undefined于iOS 12及以下版本,因此我们需要针对该场景的其他解决方案...

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

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

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

    }

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

添加Modernizr测试时,应尽可能添加针对功能而不是设备或操作系统的测试。如果需要的话,添加十项针对iPhone的测试完全没有错。有些东西只是无法检测到。

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

例如,在iPhone(不是iPad)上的视频无法在网页上内联播放,它将打开全屏显示。所以我创建了一个测试“无页内视频”

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

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

这将在iPhone上隐藏视频(在这种情况下,我实际上正在做的是显示带有单击单击的替代图像来播放视频-我只是不希望显示默认的视频播放器和播放按钮)。

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

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

 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模拟器

更新:这不包括台式机模式下的 iPad (因此不包括默认的iPadOS 13)。

这对我的用例很好,如果不适合您,请参阅Justin和kikiwora的答案。

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

    const isIOS = [
      'iPad Simulator',
      'iPhone Simulator',
      'iPod Simulator',
      'iPad',
      'iPhone',
      'iPod',
    ].indexOf(navigator.platform) !== -1;

您也可以使用 includes

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

在我的情况下,用户代理还不够好,因为在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
}

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

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

本文地址:http://javascript.askforanswer.com/jianceshebeishifouweiios.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!