Détecter si l'appareil est iOS

409

Je me demande s'il est possible de détecter si un navigateur fonctionne sur iOS, de la même manière que vous pouvez détecter avec Modernizr (bien que ce soit évidemment la détection d'appareil plutôt que la détection de fonctionnalité).

Normalement, je préférerais la détection des fonctionnalités, mais je dois savoir si un appareil est iOS en raison de la façon dont ils gèrent les vidéos conformément à cette question. L' API YouTube ne fonctionne pas avec iPad / iPhone / appareil non Flash

SparrwHawk
la source
Voir [Qu'est-ce que la chaîne d'agent utilisateur iOS 5?] [1] (en double?). [1]: stackoverflow.com/questions/7825873/…
dejuknow
1
S'agit-il d'une détection côté client ou côté serveur?
Douglas Greenshields
Hé @DouglasGreenshields, c'est côté client
SparrwHawk
1
Aussi, pas un doublon, je demande comment le faire. Je n'ai jamais utilisé de reniflement d'agent utilisateur auparavant.
SparrwHawk

Réponses:

822

Détection d'iOS

Je ne suis pas un fan de reniflement d'agent utilisateur, mais voici comment vous le feriez:

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

Une autre façon repose sur navigator.platform:

var iOS = navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);

iOSsera soit trueoufalse

Pourquoi pas MSStream

Microsoft a injecté le mot iPhone dans IE11 userAgentafin d'essayer de tromper Gmail d'une manière ou d'une autre. Nous devons donc l'exclure. Plus d'informations ici et ici .

Ci-dessous, la mise à jour d'IE11 userAgent(Internet Explorer pour 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) comme iPhone OS 7_0_3 Mac OS X AppleWebKit / 537 (KHTML, comme Gecko) Safari mobile / 537


Ajoutez facilement plus d'appareils, sans utiliser d'expressions régulières:

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()sera soit trueoufalse

Remarque: Les deux navigator.userAgentet navigator.platformpeuvent être falsifiés par l'utilisateur ou une extension de navigateur.


Détection de la version iOS

La façon la plus courante de détecter la version iOS consiste à l' analyser à partir de la chaîne de l'agent utilisateur . Mais il existe également une inférence de détection de fonctionnalité * ;

Nous savons pour un fait qui a history APIété introduit dans iOS4 - matchMedia APIdans iOS5 - webAudio APIdans iOS6 - WebSpeech APIdans iOS7 et ainsi de suite ..

Remarque: Le code suivant n'est pas fiable et se cassera si l'une de ces fonctionnalités HTML5 est déconseillée dans une version iOS plus récente. Tu étais prévenu!

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';
}
Pierre
la source
2
Merci Pierre - ce code semble plus simple cependant, je me demande simplement si je peux simplement spécifier 'iOS' plutôt que d'avoir à taper tous les iDevices séparés .... if ((navigator.userAgent.match (/ iPhone / i)) | | (navigator.userAgent.match (/ iPod / i)) || (navigator.userAgent.match (/ iPad / i))) {// Faites quelque chose}
SparrwHawk
9
Ce que vous faites dans le deuxième extrait est l'inférence des fonctionnalités, pas la détection des fonctionnalités. La détection des fonctionnalités teste les fonctionnalités que vous allez réellement utiliser, tandis que vous testez les fonctionnalités que vous savez avoir été introduites dans une version particulière du système d'exploitation et en déduire la version du système d'exploitation. Ceci est fragile car les futures versions d'iOS pourraient supprimer ces fonctionnalités.
Tim Down le
23
Voici une meilleure façon de rédiger votre chèque:var iOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
LandonSchropp
5
Juste une note - le tableau navigator.platform ne fonctionne pas sur l'iPad Simulator car il contient la phrase entière "iPad Simulator" dans la chaîne de la plate-forme.
Kevin Newman
9
Depuis iOS 13, l'agent utilisateur de l'iPad est Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15
devenu
38

Après iOS 13, vous devriez détecter les appareils iOS comme celui-ci, car l'iPad ne sera pas détecté en tant qu'appareil iOS par les anciennes méthodes (en raison des nouvelles options "de bureau", activées par défaut):

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

La première condition pour iOS <13 ou iPhone ou iPad avec le mode Bureau désactivé, la deuxième condition pour iPadOS 13 dans la configuration par défaut, car il se positionne comme Macintosh Intel, mais est en fait le seul Macintosh avec multi-touch.

Plutôt un hack qu'une vraie solution, mais fonctionne de manière fiable pour moi

PS Comme cela a été dit plus tôt, vous devriez probablement ajouter une vérification IE

let isIOS = (/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&
!window.MSStream
kikiwora
la source
Pourquoi ne pas utiliser le navigator.userAgentpour cette vérification /iPad|iPhone|iPod/.test(navigator.platform)? Il semble que navigator.platformrenvoie toujours «MacIntel» pour iPhone iOS <= 12
Charis Theo
@CharisTheo Parce que l'iPad n'est pas dans userAgent dans iOS> = 13
Kzrbill
mais vous vérifiez déjà pour iPad iOS> = 13 lors de la deuxième vérification ou est-ce que je manque quelque chose?
Charis Theo
navigator.maxTouchPointsn'est pas pris en charge dans iOS, de sorte que la vérification ne fera rien pour vous.
PaulC
@PaulC, vous avez raison en ce que maxTouchPoints n'est pas défini pour iOS 12 et inférieur, mais kikiwora est sur la bonne voie puisque maxTouchPoints est pris en charge dans iOS 13. Voir ma réponse.
Bob Arlof
14

Cela définit la variable _iOSDevicesur vrai ou faux

_iOSDevice = !!navigator.platform.match(/iPhone|iPod|iPad/);
Vitim.us
la source
3
qu'est-ce que !! faire?
patrick
4
@astronought double négation est utilisé pour lancer un booléen
Vitim.us
2
@astronought bang bang, vous êtes booléen: D
Qback
1
En utilisant, /iPhone|iPod|iPad/.test(navigator.platform)vous pouvez éviter le!!
lionello
10

Si vous utilisez Modernizr , vous pouvez lui ajouter un test personnalisé.

Peu importe le mode de détection que vous décidez d'utiliser (userAgent, navigator.vendor ou navigator.platform), vous pouvez toujours le boucler pour une utilisation plus facile plus tard.

//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');
}
ThiagoPXP
la source
2
Attention, Modernizr met automatiquement en minuscule le nom du test ajouté. (dans votre exemple, Modernizr.isiOS ne reviendra jamais vrai). Mauvais comportement de la lib à mon avis ...
Cétia
3
Tout petit avis: vous pouvez simplifier return x ? true : falseà return Boolean(x)ou tout simplementreturn !!x
Tibalt
6

Une version simplifiée et facile à étendre.

var iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;
Kory Nunn
la source
1
Si vous voulez aussi que cela fonctionne sur iOS Simulator , vous pouvez utiliser: navigator.platform.replace(' Simulator', '').
Koraktor
Mais cela ne fonctionne pas, car['str'].indexOf('string') == -1
tibalt
navigator.platform sera exactement «iPad», «iPhone» ou «iPod» sauf si le simulateur est en cours d'exécution.
Kory Nunn
4

Il vaut probablement la peine de répondre que les iPads exécutant iOS 13 auront été navigator.platformconfigurés MacIntel, ce qui signifie que vous devrez trouver un autre moyen de détecter les appareils iPadOS.

Justin Searls
la source
3

J'ai écrit cela il y a quelques années, mais je pense que cela fonctionne toujours:

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

    }
Michael Bénin
la source
2

Les agents utilisateurs sur les appareils iOS indiquent l'iPhone ou l'iPad. Je filtre simplement en fonction de ces mots clés.

Bryan Naegele
la source
4
Il y a aussi les iPod Touch à considérer.
Douglas Greenshields
@DouglasGreenshields Correct. J'ai oublié celui-là mais je crois qu'il transmet également son identité dans l'agent utilisateur.
Bryan Naegele
L'agent utilisateur de l'iPad safari n'inclura plus "iPad" d'iPadOS 13.
Jonny
2

Dans la mesure du possible, lors de l'ajout de tests Modernizr, vous devez ajouter un test pour une fonctionnalité plutôt qu'un appareil ou un système d'exploitation. Il n'y a rien de mal à ajouter dix tests tous les tests pour iPhone si c'est ce qu'il faut. Certaines choses ne peuvent tout simplement pas être détectées.

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

Par exemple, sur l'iPhone (pas l'iPad), la vidéo ne peut pas être lue en ligne sur une page Web, elle s'ouvre en plein écran. J'ai donc créé un test «pas de vidéo en page»

Vous pouvez ensuite l'utiliser dans css (Modernizr ajoute une classe .no-inpagevideoà la <html>balise si le test échoue)

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

Cela masquera la vidéo sur iPhone (ce que je fais en fait dans ce cas est de montrer une image alternative avec un onclick pour lire la vidéo - je ne veux tout simplement pas que le lecteur vidéo par défaut et le bouton de lecture s'affichent).

Simon_Weaver
la source
iOS10 le permet maintenant pour playsinlineque vous puissiez l'utiliser 'playsInline' in document.createElement('video');comme test maintenant github.com/Modernizr/Modernizr/issues/2077
Simon_Weaver
2

Wow, beaucoup de code délicat et long ici. Restez simple, s'il vous plaît!

Celui-ci est IMHO rapide, enregistre et fonctionne bien:

 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);
  • Il est rapide parce que les contrôles de la regexp ^ s epuis position de la première chaîne de plate - forme et arrête s'il n'y a pas « iP » (plus rapide que la recherche de la longue série UA jusqu'à la fin de toute façon)
  • C'est plus sûr que la vérification UA ​​(en supposant que navigator.platform est moins susceptible d'être truqué)
  • Détecte le simulateur iPhone / iPad


MISE À JOUR: Cela ne couvre pas l'iPad en mode bureau (et donc l'iPadOS 13 par défaut).
C'est bien pour mes cas d'utilisation, si ce n'est pas pour vous, voir les réponses de Justin et kikiwora.

jj
la source
iOS = /^(iPhone|iPad|iPod)/.test(navigator.platform);plutôt que cela, je ferais iOS = /^(iPhone|iPad|iPod)/.test(navigator.userAgent || navigator.vendor || navigator.platform); une mesure de secours cuz dans mon cas, navigator.platform ne fonctionnait pas, mais le faire comme plus tard fonctionnait bien
Coderboi
navigator.platformn'a pas fonctionné? Êtes-vous vraiment sur iOS alors?. Vérifiez auprès de jeka.info/test/navigator.html . userAgentdonne des faux positifs parce que certains fournisseurs le simulent pour imiter les appareils Apple pour quelque raison que ce soit. vendorjuste retourne soit Google Inc., Apple Computer, Inc.ou rien (dans Firefox).
J.-J.
1

Mettez légèrement à jour la première réponse en utilisant une approche plus fonctionnelle.

    const isIOS = [
      'iPad Simulator',
      'iPhone Simulator',
      'iPod Simulator',
      'iPad',
      'iPhone',
      'iPod',
    ].indexOf(navigator.platform) !== -1;
Sten Muchow
la source
Ne fonctionne pas dans le simulateur mobile des outils de développement Brave / Chrome. Je reçoisMacIntel
sdfsdf
1

Vous pouvez aussi utiliser includes

  const isApple = ['iPhone', 'iPad', 'iPod'].includes(navigator.platform)
Alan
la source
1

Aucune des réponses précédentes ne fonctionne pour tous les principaux navigateurs sur toutes les versions d'iOS, y compris iOS 13. Voici une solution qui fonctionne pour Safari, Chrome et Firefox pour toutes les versions d'iOS:

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

Notez que cet extrait de code a été écrit en priorité sur la lisibilité, pas sur la concision ou les performances.

Explication:

  • Si l'agent utilisateur contient l'un des "iPod | iPhone | iPad", alors clairement l'appareil est iOS. Sinon, continuez ...

  • Tout autre agent utilisateur qui ne contient pas "Macintosh" n'est pas un appareil Apple et ne peut donc pas être iOS. Sinon, c'est un appareil Apple, alors continuez ...

  • S'il maxTouchPointsa une valeur 1supérieure ou égale à, l'appareil Apple a un écran tactile et doit donc être iOS car il n'y a pas de Mac avec écran tactile (bravo à kikiwora pour le mentionner maxTouchPoints). Notez que maxTouchPointsc'est undefinedpour iOS 12 et inférieur, nous avons donc besoin d'une solution différente pour ce scénario ...

  • iOS 12 et les versions antérieures ont une bizarrerie qui n'existe pas sous Mac OS. La particularité est que la volumepropriété d'un Audioélément ne peut pas être définie avec succès sur une valeur autre que 1. En effet, Apple n'autorise pas les changements de volume sur l' Audioélément pour les appareils iOS, mais le permet pour Mac OS. Cette bizarrerie peut être utilisée comme méthode de secours finale pour distinguer un appareil iOS d'un appareil Mac OS.

Bob Arlof
la source
-1

Dans mon cas, l'agent utilisateur n'était pas assez bon car dans l'Ipad, l'agent utilisateur était le même que sous Mac OS, j'ai donc dû faire un mauvais tour:

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
}
Ian Farré
la source
il suffit de lire la question qui dit détecter iOS, pas détecter mobile
Cybersupernova
-2

Afin de détecter la version iOS, il faut détruire l'agent utilisateur avec un code Javascript comme celui-ci:

 var res = navigator.userAgent.match(/; CPU.*OS (\d_\d)/);
    if(res) {
        var strVer = res[res.length-1];
        strVer = strVer.replace("_", ".");
        version = strVer * 1;
    }
viebel
la source
-2

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

Mithun Sreedharan
la source