检测设备是否为iOS

发布于 2024-12-29 04:23:51 字数 288 浏览 4 评论 0原文

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

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

I'm wondering if it's possible to detect whether a browser is running on iOS, similar to how you can feature detect with Modernizr (although this is obviously device detection rather than feature detection).

Normally I would favour feature detection instead, but I need to find out whether a device is iOS because of the way they handle videos as per this question YouTube API not working with iPad / iPhone / non-Flash device

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(24

海螺姑娘 2025-01-05 04:23:51

检测 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.userAgentnavigator.platform 都可以被用户或浏览器扩展程序伪造。

用于更改 userAgent 或平台的浏览器扩展之所以存在,是因为网站使用过于严厉的检测,并且经常禁用某些功能,即使用户的浏览器本来可以使用该功能。

为了缓和与用户的冲突,建议针对每种情况专门检测您的网站所需的确切功能。然后,当用户获得具有所需功能的浏览器时,它已经可以正常工作,而无需进行额外的代码更改。

检测 iOS 版本

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

我们知道 history API 是在 iOS4 中引入的 - matchMedia APIiOS5 中引入 - webAudio iOS6 中的 API - iOS7 中的 WebSpeech API 等等。

注意:以下代码不可靠,如果在较新的 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';
}

Detecting iOS

With iOS 13 iPad both User agent and platform strings are changed and differentiating between iPad and MacOS seems possible, so all answers below needs to take that into account now.

This might be the shortest alternative that also covers 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 will be either true or false

Worse option: User agent sniffing

User Agent sniffing is more dangerous and problems appear often.

On iPad iOS 13, the user agent is identical with that of a MacOS 13 computer, but if you ignore iPads this might work still for a while:

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

The !window.MSStream is to not incorrectly detect IE11, see here and here.

Note: Both navigator.userAgent and navigator.platform can be faked by the user or a browser extension.

Browser extensions to change userAgent or platform exist because websites use too heavy-handed detection and often disable some features even if the user's browser would otherwise be able to use that feature.

To de-escalate this conflict with users it's recommended to detect specifically for each case the exact features that your website needs. Then when the user gets a browser with the needed feature it will already work without additional code changes.

Detecting iOS version

The most common way of detecting the iOS version is by parsing it from the User Agent string. But there is also feature detection inference*;

We know for a fact that history API was introduced in iOS4 - matchMedia API in iOS5 - webAudio API in iOS6 - WebSpeech API in iOS7 and so on.

Note: The following code is not reliable and will break if any of these HTML5 features is deprecated in a newer iOS version. You have been warned!

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';
}
很糊涂小朋友 2025-01-05 04:23:51

iPad 检测为 iOS 设备(由于新的“桌面”选项,默认启用):

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

在 iOS 13 之后,您应该像这样检测 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

After iOS 13 you should detect iOS devices like this, since iPad will not be detected as iOS devices by old ways (due to new "desktop" options, enabled by default):

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

The first condition for iOS < 13 or iPhone or iPad with disabled Desktop mode, the second condition for iPadOS 13 in the default configuration, since it position itself like Macintosh Intel, but actually is the only Macintosh with multi-touch.

Rather a hack than a real solution, but work reliably for me

P.S. As being said earlier, you probably should add IE checkup

let isIOS = (/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&
!window.MSStream
一生独一 2025-01-05 04:23:51

这里之前的答案都不适用于所有版本的 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,因为没有带触摸屏的 Mac(感谢 kikiwora 提到 maxTouchPoints)。请注意,对于 iOS 12 及更低版本,maxTouchPoints未定义,因此我们需要针对该场景使用不同的解决方案...

  • iOS 12 及更低版本有一个怪癖,它不会存在于 Mac 操作系统中。奇怪的是,Audio 元素的 volume 属性无法成功设置为 1 之外的任何值。这是因为 Apple 不允许在 iOS 设备上更改 Audio 元素的音量,但在 Mac OS 上则允许。该特性可用作区分 iOS 设备与 Mac OS 设备的最终后备方法。

None of the previous answers here work for all major browsers on all versions of iOS, including iOS 13. Here is a solution that works for Safari, Chrome and Firefox for all iOS versions:

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

Note that this code snippet was written with priority on readability, not conciseness or performance.

Explanation:

  • If the user agent contains any of "iPod|iPhone|iPad" then clearly the device is iOS. Otherwise, continue...

  • Any other user agent that does not contain "Macintosh" is not an Apple device and therefore cannot be iOS. Otherwise, it is an Apple device, so continue...

  • If maxTouchPoints has a value of 1 or greater then the Apple device has a touch screen and therefore must be iOS since there are no Macs with touch screens (kudos to kikiwora for mentioning maxTouchPoints). Note that maxTouchPoints is undefined for iOS 12 and below, so we need a different solution for that scenario...

  • iOS 12 and below has a quirk that does not exist in Mac OS. The quirk is that the volume property of an Audio element cannot be successfully set to any value other than 1. This is because Apple does not allow volume changes on the Audio element for iOS devices, but does for Mac OS. That quirk can be used as the final fallback method for distinguishing an iOS device from a Mac OS device.

相守太难 2025-01-05 04:23:51

这会将变量 _iOSDevice 设置为 truefalse

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

This sets the variable _iOSDevice to true or false

_iOSDevice = !!navigator.platform.match(/iPhone|iPod|iPad/);
怼怹恏 2025-01-05 04:23:51

2018 年原始答案(可能已过时,具体取决于用例)
哇,这里有很多冗长而棘手的代码。请保持简单!恕我直言,这个速度快,保存好,运行良好:

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

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

更新2019-09:我原来的答案不包括桌面模式的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;

更新 2024 替代方案

// in 2024 we don't care about IE 11 throwing an error and can do this:

iOSiPadOS = navigator.platform.startsWith("iP") ||
    navigator.platform.startsWith("Mac") && navigator.maxTouchPoints > 4;
  • 两者都应该安全,只要
    • 台式机 Mac 根本不支持触摸事件
    • 或不超过 4 个触摸点(当前 iOS 设备支持 5 个触摸点)
  • 速度很快,因为正则表达式 ^ 首先检查起始位置平台字符串的位置,如果没有“iP”则停止(无论如何都比搜索长 UA 字符串直到末尾更快)
  • navigator.userAgent 检查更安全 navigator.platform 伪造的可能性要小得多
  • 检测 iPhone / iPad 模拟器

ORIGINAL ANSWER 2018 (may be outdated, depending on usecase)
Wow, a lot of longish tricky code here. Keep it simple, please! This one is IMHO fast, save, and working well:

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

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

UPDATE 2019-09: My original answer doesn't cover iPad in desktop mode (the default changes to desktop mode in upcoming iPadOS 13 and higher).

That's fine for my usecases, if it's not for you, use this update:

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

iOSiPadOS = /^iP/.test(navigator.platform) ||
           /^Mac/.test(navigator.platform) && navigator.maxTouchPoints > 4;

UPDATE 2024 alternative

// in 2024 we don't care about IE 11 throwing an error and can do this:

iOSiPadOS = navigator.platform.startsWith("iP") ||
    navigator.platform.startsWith("Mac") && navigator.maxTouchPoints > 4;
  • Both should be safe as long as
    • desktop Macs don't support touch events at all
    • or not more than 4 touch points (current iOS devices support 5 touch points)
  • It's fast because the regexp ^ first checks the starting position of the platform string and stops if there is no "iP" (faster than searching the long UA string until the end anyway)
  • It's safer than navigator.userAgent check as navigator.platform is much less likely faked
  • Detects iPhone / iPad Simulator
零度℉ 2025-01-05 04:23:51

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

If you are using Modernizr, you can add a custom test for it.

It doesn't matter which detection mode you decide to use (userAgent, navigator.vendor or navigator.platform), you can always wrap it up for a easier use later.

//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');
}
假装爱人 2025-01-05 04:23:51

一个简化的、易于扩展的版本。

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

A simplified, easy to extend version.

var iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;
孤独患者 2025-01-05 04:23:51

正在检测 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());

Detecting iOS (both <12, and 13+)

Community wiki, as edit queue says it is full and all other answers are currently outdated or incomplete.

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());
旧伤还要旧人安 2025-01-05 04:23:51

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

It's probably worth answering that iPads running iOS 13 will have navigator.platform set to MacIntel, which means you'll need to find another way to detect iPadOS devices.

暮光沉寂 2025-01-05 04:23:51

无需测试 navigator.userAgentnavigator.platform

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

navigator.standalone 仅在 iOS Safari 上设置。请参阅 MDN Safari HTML 参考

There is no need to test navigator.userAgent or navigator.platform:

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

navigator.standalone is only set on iOS Safari. See MDN, Safari HTML Reference.

那支青花 2025-01-05 04:23:51

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

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

    }

I wrote this a couple years ago but i believe it still works:

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

    }
初见 2025-01-05 04:23:51

在添加 Modernizr 测试时,您应该尽可能添加针对功能的测试,而不是针对设备或操作系统的测试。如果需要的话,添加十个测试来测试 iPhone 并没有什么问题。有些东西就是无法被特征检测到。

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

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

然后您可以在 css 中使用它(Modernizr 将类 .no-inpagevideo 添加到 标记,如果测试失败)

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

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

Wherever possible when adding Modernizr tests you should add a test for a feature, rather than a device or operating system. There's nothing wrong with adding ten tests all testing for iPhone if that's what it takes. Some things just can't be feature detected.

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

For instance on the iPhone (not the iPad) video cannot be played inline on a webpage, it opens up full screen. So I created a test 'no-inpage-video'

You can then use this in css (Modernizr adds a class .no-inpagevideo to the <html> tag if the test fails)

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

This will hide the video on iPhone (what I'm actually doing in this case is showing an alternative image with an onclick to play the video - I just don't want the default video player and play button to show).

欢烬 2025-01-05 04:23:51

如果您使用 React,有一个很棒的库可以解决此类问题:REACT-UGENT。 (使用 ua-parser-js 构建。)

https://github.com/medipass/react-ugent< /a>

可用的浏览器有:

chrome、chromium、edge、firefox、ie、lynx、safari、opera

可用的操作系统是:

android、blackberry、chromium os、debian、ios、linux、mac os、ubuntu、unix、windows

可用设备是:

控制台、计算机、手机、平板电脑、smarttv、可穿戴设备、嵌入式

易于使用:

<Ugent browser="safari" os="ios">
  <div>
    This text only shows on Safari on iOS.
  </div>
</Ugent>

如果你不使用 React,基本上,你可以使用 - ua-parser-js

https://github.com/faisalman/ua-parser-js

If you're using React, There is great library for this kind of issues: REACT-UGENT. (Built with ua-parser-js.)

https://github.com/medipass/react-ugent

Available browsers are:

chrome, chromium, edge, firefox, ie, lynx, safari, opera

Available OS are:

android, blackberry, chromium os, debian, ios, linux, mac os, ubuntu, unix, windows

Available devices are:

console, computer, mobile, tablet, smarttv, wearable, embedded

Easy to use as:

<Ugent browser="safari" os="ios">
  <div>
    This text only shows on Safari on iOS.
  </div>
</Ugent>

If you're not using React, basically, you can use - ua-parser-js

https://github.com/faisalman/ua-parser-js

在风中等你 2025-01-05 04:23:51

如果您仍在尝试检查是否是 iOS,我建议您使用以下方法:

  1. 创建一个名为 helper 的文件夹
  2. 创建一个名为 platform.tsplatform.js
  3. 导出函数isIOS
export const isIOS = () => {
    let platform = navigator?.userAgent || navigator?.platform || 'unknown'

    return /iPhone|iPod|iPad/.test(platform)
}

如果是iPhone,结果将为true iPodIpad 或者它将是false 否则。

你可能会问,为什么我需要检查 navigator.userAgent || navigator.platform,原因很简单,第二个选项曾经是默认选项,但现在它已被弃用,并且某些浏览器将来将停止支持它,第一个选项更可靠。

您可以在此处查看我上面提到的弃用:

https://developer.mozilla.org/en-US/docs/Web/API/Navigator/platform#:~:text=Deprecated%3A%20This%20feature%20is%20no,be%20kept%20for% 20兼容性%20目的

记录 userAgentDatauserAgentplatform

使用下面的函数,我收到了这些日志:

    console.log({
        userAgentData: navigator?.userAgentData?.platform,
        userAgent: navigator?.userAgent,
        platform: navigator?.platform,
    })

    {
        "userAgentData": "",
        "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1",
        "platform": "MacIntel"
    }

我在我的 Macbook 上测试它,它可以在不同的浏览器和操作系统上运行。因此,正如您所看到的 navigator?.userAgentData?.platform 根本不起作用。

即使我使用 React 来调用此函数,我也没有收到与打字稿相关的任何错误

Bonus,isAndroid

如果您想知道如何检查是否是 Android 平台,我建议您不要遵循与 isIOS 相反的想法:

const isAndroid = !isIOS();

原因很简单,它不会工作,因为桌面将被识别为 Android 平台。
要解决这个问题,您只需要执行以下检查:

export const isAndroid = () => {
    const ua = navigator.userAgent.toLowerCase() + navigator?.platform.toLowerCase();
    const isAndroid = ua.indexOf("android") > -1;

    return isAndroid;
}

我们检查 navigator.userAgentnavigator?.platform 的原因是为了支持旧浏览器和新浏览器。

If you are still trying to check if is iOS or not, I recommend you to use this approach:

  1. Create a folder called helper
  2. Create a file called platform.ts or platform.js
  3. Export the function isIOS:
export const isIOS = () => {
    let platform = navigator?.userAgent || navigator?.platform || 'unknown'

    return /iPhone|iPod|iPad/.test(platform)
}

The result will be true if is an iPhone or iPod or Ipad or it will be false otherwise.

You may ask, why do I need to check navigator.userAgent || navigator.platform, well the reason is simple the second option used to be the default one but now it is deprecated and some browsers will stop supporting this in the future, the first one is more reliable.

You can check here about the deprecation that I mentioned above:

https://developer.mozilla.org/en-US/docs/Web/API/Navigator/platform#:~:text=Deprecated%3A%20This%20feature%20is%20no,be%20kept%20for%20compatibility%20purposes.

Logging the userAgentData, userAgent and platform.

Using the function below, I received these logs:

    console.log({
        userAgentData: navigator?.userAgentData?.platform,
        userAgent: navigator?.userAgent,
        platform: navigator?.platform,
    })

    {
        "userAgentData": "",
        "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1",
        "platform": "MacIntel"
    }

I was testing it on my Macbook and it worked on different browsers and operation systems. So, as you can see navigator?.userAgentData?.platform will not work at all.

I also didn't receive any errors related to my typescript, even though that I am using React to call this function.

Bonus, isAndroid

If you wondering how to check if is an Android platform, I suggest you don't follow the idea of doing the opposite of isIOS as:

const isAndroid = !isIOS();

The reason is quite simple, it will not work since desktops will be recognized as an Android platform.
To solve this problem you just need to do this check:

export const isAndroid = () => {
    const ua = navigator.userAgent.toLowerCase() + navigator?.platform.toLowerCase();
    const isAndroid = ua.indexOf("android") > -1;

    return isAndroid;
}

The reason why we are checking navigator.userAgent plus navigator?.platform is to support old browsers and the new ones.

难以启齿的温柔 2025-01-05 04:23:51

利用 Apple Pay JS API 检查

`if (window.dw && window.dw.applepay && window.ApplePaySession && window.ApplePaySession.canMakePayments()) {

// do the needful

}`

Make use of Apple Pay JS API checks

`if (window.dw && window.dw.applepay && window.ApplePaySession && window.ApplePaySession.canMakePayments()) {

// do the needful

}`

恍梦境° 2025-01-05 04:23:51

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

The user-agents on iOS devices say iPhone or iPad in them. I just filter based on those keywords.

欢你一世 2025-01-05 04:23:51

因为 navigator.platform 已被弃用,最好不再使用它,所以我想添加其他解决方案。

您可以通过检查 navigator.vendor 在 MacOS 系统上进行过滤。
当结果是 Apple Computer, Inc. 时,您就知道它是 MacOS。

Because navigator.platform is deprecated and it is better to not use it anymore, I want to add an other solution.

You can filter on MacOS systems by checking the navigator.vendor.
When the outcome is Apple Computer, Inc., you know it is MacOS.

秋千易 2025-01-05 04:23:51

这是我经历了很多痛苦之后的解决方案,它并不完美,但希望能帮助别人,我已经尝试过了,它完全针对 iPad safari。

function detectSafariOnIpadOS() {
  var userAgent = navigator.userAgent;
  var isSafari = /^((?!chrome|android).)*safari/i.test(userAgent);
  var isIpad = /iPad/i.test(userAgent);
  var isMacintosh = /Macintosh/i.test(userAgent);
  var isTouchDevice = "ontouchend" in document;

  console.log("User Agent:", userAgent);
  console.log("detectSafariOnIpadOS result:", isSafari && (isIpad || (isMacintosh && isTouchDevice)));

return isSafari && (isIpad || (isMacintosh && isTouchDevice));
}

this was my solution after suffering a lot its not perfect but hope to help someone, I have tried it and it’s and it exactly target iPad safari.

function detectSafariOnIpadOS() {
  var userAgent = navigator.userAgent;
  var isSafari = /^((?!chrome|android).)*safari/i.test(userAgent);
  var isIpad = /iPad/i.test(userAgent);
  var isMacintosh = /Macintosh/i.test(userAgent);
  var isTouchDevice = "ontouchend" in document;

  console.log("User Agent:", userAgent);
  console.log("detectSafariOnIpadOS result:", isSafari && (isIpad || (isMacintosh && isTouchDevice)));

return isSafari && (isIpad || (isMacintosh && isTouchDevice));
}
救赎№ 2025-01-05 04:23:51

对于任何希望遵守 PageSpeed Insights 和 Lighthouse 最佳实践(标记在控制台中发现的使用 navigator.userAgent (等)的“问题”)的人,这可以帮助您(我从 Boostrap 收集到这一点) 5):

function getUAString() {
    let uaData = navigator.userAgentData;
    if (null !== uaData && uaData.brands) {
        return uaData.brands.map(item => item.brand + '/' + item.version).join(' ');
    }
    return navigator.userAgent;
}

const isIOS = /iP(hone|od|ad)/.test(getUAString());

For anyone looking to be compliant with PageSpeed Insights and Lighthouse best practices which flags "issues" found in the console for the use of navigator.userAgent (etc), this can help you (I gleaned this from Boostrap 5):

function getUAString() {
    let uaData = navigator.userAgentData;
    if (null !== uaData && uaData.brands) {
        return uaData.brands.map(item => item.brand + '/' + item.version).join(' ');
    }
    return navigator.userAgent;
}

const isIOS = /iP(hone|od|ad)/.test(getUAString());
ゝ杯具 2025-01-05 04:23:51

在一行中使其工作,包括 iPad。就我而言,当有任何 Apple 设备时,我会隐藏一个按钮。

// Hide the close button on iOS (incl. iPad iOS 13+, see "maxTouchPoints" part) in main menu.
if (!/(iPad|iPhone|iPod)/g.test(navigator.userAgent) && !navigator.maxTouchPoints) {
    this.createCloseButton();
}

Got it working, in one line, including iPad. In my case, I'm hiding a button when there's any of Apple devices.

// Hide the close button on iOS (incl. iPad iOS 13+, see "maxTouchPoints" part) in main menu.
if (!/(iPad|iPhone|iPod)/g.test(navigator.userAgent) && !navigator.maxTouchPoints) {
    this.createCloseButton();
}
败给现实 2025-01-05 04:23:51

您还可以使用包含

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

You can also use includes

  const isApple = ['iPhone', 'iPad', 'iPod', 'iPad Simulator', 'iPhone Simulator', 'iPod Simulator',].includes(navigator.platform)
×纯※雪 2025-01-05 04:23:51

就我而言,用户代理不够好,因为在 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
}

In my case the user agent was not good enought since in the Ipad the user agent was the same as in Mac OS, therefore I had to do a nasty trick:

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
}
送舟行 2025-01-05 04:23:51

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

In order to detect the iOS version, one has to destructure the user agent with a Javascript code like this:

 var res = navigator.userAgent.match(/; CPU.*OS (\d_\d)/);
    if(res) {
        var strVer = res[res.length-1];
        strVer = strVer.replace("_", ".");
        version = strVer * 1;
    }
噩梦成真你也成魔 2025-01-05 04:23:51

var isiOSSafari = (navigator.userAgent.match(/像 Mac OS X/i)) ?真:假;

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文