可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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
回答1:
Detecting iOS
I am not a fan of User Agent sniffing, but here is how you would do it:
var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
Another way is relying on navigator.platform
:
var iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
iOS
will be either true
or false
Why not MSStream
Microsoft injected the word iPhone in IE11's userAgent
in order to try and fool Gmail somehow. Therefore we need to exclude it. More info about this here and here.
Below is IE11's updated userAgent
(Internet Explorer for Windows Phone 8.1 Update):
Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 930) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537
Easily add more devices, without using Regular Expressions:
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()
will be either true
or false
Note: Both navigator.userAgent
and navigator.platform
can be faked by the user or a browser extension.
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 (/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'; }
回答2:
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'); }
回答3:
There is this custom Modernizr tests: https://gist.github.com/855078
回答4:
This sets the variable _iOSDevice
to true or false
_iOSDevice = !!navigator.platform.match(/iPhone|iPod|iPad/);
回答5:
The user-agents on iOS devices say iPhone or iPad in them. I just filter based on those keywords.
回答6:
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"); }
回答7:
A simplified, easy to extend version.
var iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;
回答8:
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
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).
回答9:
As mentioned above, you can use the user agent to determine whether you're running on iOS. As for the various edge cases - it's already taken care of :) I wrote this is-mobile component that can detect whether you're running on an iOS device, and other platforms as well, and takes into account the various edge cases.
Feel free to import it and use as shown in these examples:
isMobile.iOS() => true/false isMobile.iPhone() => true/false isMobile.iPad() => true/false isMobile.Android() => true/false isMobile.Windows() => true/false isMobile.any() => true/false
回答10:
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; }
回答11:
var isiOSSafari = (navigator.userAgent.match(/like Mac OS X/i)) ? true: false;