检测设备是否为iOS
我想知道是否可以检测浏览器是否在 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(24)
检测 iOS
使用 iOS 13 iPad 用户代理和平台字符串均已更改 和 区分 iPad 和 MacOS 似乎是可能的,因此下面的所有答案都需要考虑这一点现在考虑到。
这可能是涵盖 iOS 13 的最短替代方案:
iOS
将为true
或false
更糟糕的选择:用户代理嗅探
用户代理嗅探是更危险,问题也经常出现。
在 iPad iOS 13 上,用户代理与 MacOS 13 计算机的用户代理相同,但如果您忽略 iPad,这可能仍会工作一段时间:
!window.MSStream
是为了不错误地检测IE11,请参见此处 和 这里。注意:
navigator.userAgent
和navigator.platform
都可以被用户或浏览器扩展程序伪造。用于更改 userAgent 或平台的浏览器扩展之所以存在,是因为网站使用过于严厉的检测,并且经常禁用某些功能,即使用户的浏览器本来可以使用该功能。
为了缓和与用户的冲突,建议针对每种情况专门检测您的网站所需的确切功能。然后,当用户获得具有所需功能的浏览器时,它已经可以正常工作,而无需进行额外的代码更改。
检测 iOS 版本
检测 iOS 版本的最常见方法是从用户代理字符串中解析它。但还有特征
检测推断*;我们知道
history API
是在 iOS4 中引入的 -matchMedia API
在 iOS5 中引入 -webAudio iOS6 中的 API
- iOS7 中的WebSpeech API
等等。注意:以下代码不可靠,如果在较新的 iOS 版本中弃用其中任何 HTML5 功能,则以下代码将会中断。您已被警告!
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:
iOS
will be eithertrue
orfalse
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:
The
!window.MSStream
is to not incorrectly detect IE11, see here and here.Note: Both
navigator.userAgent
andnavigator.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
detectioninference*;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!
iPad 检测为 iOS 设备(由于新的“桌面”选项,默认启用):
在 iOS 13 之后,您应该像这样检测 iOS 设备,因为旧方法不会将 13 或 iPhone 或 iPad 禁用桌面模式,这是默认配置下 iPadOS 13 的第二个条件,因为它的定位类似于 Macintosh Intel,但实际上是唯一具有多点触控功能的 Macintosh。
与其说是一个黑客,不如说是一个真正的解决方案,但对我来说可靠地工作
PS 正如前面所说,您可能应该添加 IE 检查
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):
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
这里之前的答案都不适用于所有版本的 iOS 上的所有主要浏览器,包括 iOS 13。这是一个适用于所有 iOS 版本的 Safari、Chrome 和 Firefox 的解决方案:
请注意,此代码片段是在编写时优先考虑可读性的,不是简洁性或性能。
说明:
如果用户代理包含“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:
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 of1
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 mentioningmaxTouchPoints
). Note thatmaxTouchPoints
isundefined
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 anAudio
element cannot be successfully set to any value other than1
. This is because Apple does not allow volume changes on theAudio
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.这会将变量
_iOSDevice
设置为 true 或 falseThis sets the variable
_iOSDevice
to true or false2018 年原始答案(可能已过时,具体取决于用例)
哇,这里有很多冗长而棘手的代码。请保持简单!恕我直言,这个速度快,保存好,运行良好:
更新2019-09:我原来的答案不包括桌面模式的iPad(默认更改为桌面模式)
即将推出iPadOS 13 及更高版本)。这适合我的用例,如果不适合您,请使用此更新:
更新 2024 替代方案
^
首先检查起始位置平台字符串的位置,如果没有“iP”则停止(无论如何都比搜索长 UA 字符串直到末尾更快)navigator.userAgent
检查更安全navigator.platform
伪造的可能性要小得多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:
UPDATE 2019-09: My original answer doesn't cover iPad in desktop mode (the default changes to desktop mode in
upcomingiPadOS 13 and higher).That's fine for my usecases, if it's not for you, use this update:
UPDATE 2024 alternative
^
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)navigator.userAgent
check asnavigator.platform
is much less likely faked如果您使用 Modernizr,您可以为其添加自定义测试。
无论您决定使用哪种检测模式(userAgent、navigator.vendor 或 navigator.platform),您始终可以将其包装起来以便稍后使用。
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.
一个简化的、易于扩展的版本。
A simplified, easy to extend version.
正在检测 iOS(<12 和 13+)
社区 wiki,因为编辑队列表示它已满,并且所有其他答案当前都已过时或不完整。
Detecting iOS (both <12, and 13+)
Community wiki, as edit queue says it is full and all other answers are currently outdated or incomplete.
可能值得回答的是,运行 iOS 13 的 iPad 会将
navigator.platform
设置为MacIntel
,这意味着您需要找到另一种方法来检测 iPadOS 设备。It's probably worth answering that iPads running iOS 13 will have
navigator.platform
set toMacIntel
, which means you'll need to find another way to detect iPadOS devices.无需测试
navigator.userAgent
或navigator.platform
:navigator.standalone
仅在 iOS Safari 上设置。请参阅 MDN, Safari HTML 参考。There is no need to test
navigator.userAgent
ornavigator.platform
:navigator.standalone
is only set on iOS Safari. See MDN, Safari HTML Reference.我几年前写过这个,但我相信它仍然有效:
I wrote this a couple years ago but i believe it still works:
在添加 Modernizr 测试时,您应该尽可能添加针对功能的测试,而不是针对设备或操作系统的测试。如果需要的话,添加十个测试来测试 iPhone 并没有什么问题。有些东西就是无法被特征检测到。
例如,在 iPhone(而非 iPad)上,视频无法在网页上内嵌播放,它会全屏显示。所以我创建了一个测试“no-inpage-video”,
然后您可以在 css 中使用它(Modernizr 将类
.no-inpagevideo
添加到标记,如果测试失败)
这将隐藏 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.
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)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).
如果您使用 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、可穿戴设备、嵌入式
易于使用:
如果你不使用 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:
If you're not using React, basically, you can use - ua-parser-js
https://github.com/faisalman/ua-parser-js
如果您仍在尝试检查是否是 iOS,我建议您使用以下方法:
helper
的文件夹platform.ts
或platform.js
isIOS
:如果是
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目的。
记录
userAgentData
、userAgent
和platform
。使用下面的函数,我收到了这些日志:
我在我的 Macbook 上测试它,它可以在不同的浏览器和操作系统上运行。因此,正如您所看到的
navigator?.userAgentData?.platform
根本不起作用。即使我使用 React 来调用此函数,我也没有收到与打字稿相关的任何错误。
Bonus,isAndroid
如果您想知道如何检查是否是 Android 平台,我建议您不要遵循与
isIOS
相反的想法:原因很简单,它不会工作,因为桌面将被识别为 Android 平台。
要解决这个问题,您只需要执行以下检查:
我们检查
navigator.userAgent
和navigator?.platform
的原因是为了支持旧浏览器和新浏览器。If you are still trying to check if is iOS or not, I recommend you to use this approach:
helper
platform.ts
orplatform.js
isIOS
:The result will be
true
if is aniPhone
oriPod
orIpad
or it will befalse
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
andplatform
.Using the function below, I received these logs:
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: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:
The reason why we are checking
navigator.userAgent
plusnavigator?.platform
is to support old browsers and the new ones.利用 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
}`
iOS 设备上的用户代理称其中包含 iPhone 或 iPad。我只是根据这些关键词进行过滤。
The user-agents on iOS devices say iPhone or iPad in them. I just filter based on those keywords.
因为
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.这是我经历了很多痛苦之后的解决方案,它并不完美,但希望能帮助别人,我已经尝试过了,它完全针对 iPad safari。
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.
对于任何希望遵守 PageSpeed Insights 和 Lighthouse 最佳实践(标记在控制台中发现的使用
navigator.userAgent
(等)的“问题”)的人,这可以帮助您(我从 Boostrap 收集到这一点) 5):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):在一行中使其工作,包括
iPad
。就我而言,当有任何Apple
设备时,我会隐藏一个按钮。Got it working, in one line, including
iPad
. In my case, I'm hiding a button when there's any ofApple
devices.您还可以使用
包含
You can also use
includes
就我而言,用户代理不够好,因为在 Ipad 中,用户代理与 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:
为了检测 iOS 版本,必须使用如下 Javascript 代码来解构用户代理:
In order to detect the iOS version, one has to destructure the user agent with a Javascript code like this:
var isiOSSafari = (navigator.userAgent.match(/像 Mac OS X/i)) ?真:假;
var isiOSSafari = (navigator.userAgent.match(/like Mac OS X/i)) ? true: false;