Rileva se il dispositivo è iOS


409

Mi chiedo se è possibile rilevare se un browser è in esecuzione su iOS, in modo simile a come è possibile rilevare le funzionalità con Modernizr (sebbene questo sia ovviamente il rilevamento dei dispositivi piuttosto che il rilevamento delle funzionalità).

Normalmente preferirei invece il rilevamento delle funzionalità, ma devo scoprire se un dispositivo è iOS a causa del modo in cui gestiscono i video secondo questa domanda L' API di YouTube non funziona con iPad / iPhone / dispositivo non Flash


Vedi [Cos'è la stringa agente utente iOS 5?] [1] (duplicato?). [1]: stackoverflow.com/questions/7825873/...
dejuknow

1
Questo rilevamento è lato client o lato server?
Douglas Greenshields

Ehi @DouglasGreenshields, è lato client
SparrwHawk,

1
Inoltre, non un duplicato, sto chiedendo come farlo. Non ho mai usato lo sniffing user-agent prima d'ora.
SparrwHawk,

Risposte:


822

Rilevamento di iOS

Non sono un fan dello sniffing di User Agent, ma ecco come lo faresti:

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

Un altro modo è fare affidamento su navigator.platform:

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

iOSsarà o trueofalse

Perché non MSStream

Microsoft ha inserito la parola iPhone in IE11 userAgentper cercare di ingannare Gmail in qualche modo. Pertanto dobbiamo escluderlo. Maggiori informazioni su questo qui e qui .

Di seguito è aggiornato IE11 userAgent( aggiornamento di Internet Explorer per Windows Phone 8.1):

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) come iPhone OS 7_0_3 Mac OS X AppleWebKit / 537 (KHTML, come Gecko) Safari mobile / 537


Aggiungi facilmente più dispositivi, senza utilizzare le espressioni regolari:

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()sarà o trueofalse

Nota: entrambi navigator.userAgente navigator.platformpossono essere simulati dall'utente o da un'estensione del browser.


Rilevamento della versione iOS

Il modo più comune di rilevare la versione di iOS è analizzarla dalla stringa User Agent . Ma c'è anche un'inferenza sul rilevamento delle caratteristiche * ;

Sappiamo per certo che è history APIstato introdotto in iOS4 - matchMedia APIin iOS5 - webAudio APIin iOS6 - WebSpeech APIin iOS7 e così via ...

Nota: il codice seguente non è affidabile e si interromperà se una di queste funzionalità HTML5 è obsoleta in una versione iOS più recente. Sei stato avvertito!

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
Grazie Pierre - questo codice sembra più semplice, mi chiedo solo se posso semplicemente specificare 'iOS' piuttosto che dover digitare tutti i iDevices separati .... if ((navigator.userAgent.match (/ iPhone / i)) | | (navigator.userAgent.match (/ iPod / i)) || (navigator.userAgent.match (/ iPad / i))) {// Fai qualcosa}
SparrwHawk,

9
Quello che stai facendo nel secondo frammento è l'inferenza di funzionalità, non il rilevamento di funzionalità. Il rilevamento delle funzionalità sta testando le funzionalità che stai effettivamente utilizzando, mentre quello che stai facendo è testare le funzionalità che ti capita di sapere sono state introdotte in una particolare versione del sistema operativo e ne deducono la versione del sistema operativo. Questo è fragile perché le future versioni di iOS potrebbero rimuovere queste funzionalità.
Tim Down

23
Questo è un modo migliore per scrivere il tuo assegno:var iOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
LandonSchropp

5
Solo una nota: l'array navigator.platform non funziona su iPad Simulator perché contiene l'intera frase "iPad Simulator" nella stringa della piattaforma.
Kevin Newman,

9
Da iOS 13 l'agente dell'utente dell'iPad è cambiato in "Mac OS", ad esempio: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15quindi questa risposta deve essere aggiornata
zvi

38

Dopo iOS 13 dovresti rilevare i dispositivi iOS in questo modo, poiché iPad non verrà rilevato come dispositivi iOS da vecchi metodi (a causa delle nuove opzioni "desktop", abilitate per impostazione predefinita):

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

La prima condizione per iOS <13 o iPhone o iPad con modalità Desktop disabilitata, la seconda condizione per iPadOS 13 nella configurazione predefinita, poiché si posiziona come Macintosh Intel, ma in realtà è l'unico Macintosh con multi-touch.

Piuttosto un trucco piuttosto che una soluzione reale, ma lavora in modo affidabile per me

PS Come detto prima, probabilmente dovresti aggiungere IE checkup

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

Perché non usare il navigator.userAgentper questo controllo /iPad|iPhone|iPod/.test(navigator.platform)? Sembra che navigator.platformritorni sempre "MacIntel" per iPhone iOS <= 12
Charis Theo,

@CharisTheo Perché iPad non è in userAgent in iOS> = 13
Kzrbill

ma stai già verificando iPad iOS> = 13 nel secondo controllo o mi sto perdendo qualcosa?
Charis Theo,

navigator.maxTouchPointsnon è supportato in iOS, quindi quel segno di spunta non farà nulla per te.
PaulC

@PaulC, hai ragione nel dire che maxTouchPoints non è definito per iOS 12 e versioni precedenti, ma kikiwora è sulla buona strada poiché maxTouchPoints è supportato in iOS 13. Vedi la mia risposta.
Bob Arlof,

14

Questo imposta la variabile _iOSDevicesu vero o falso

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

3
cosa fa !! fare?
patrick,

4
La doppia negazione di @astronought viene usata per lanciare un booleano
Vitim.us

2
@astronought bang bang, sei booleano: D
Qback il

1
Usando /iPhone|iPod|iPad/.test(navigator.platform)puoi evitare il!!
lionello

10

Se stai usando Modernizr , puoi aggiungere un test personalizzato per questo.

Indipendentemente dalla modalità di rilevamento che decidi di utilizzare (userAgent, navigator.vendor o navigator.platform), puoi sempre completarla per un uso più semplice in seguito.

//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');
}

2
Attenzione, Modernizr mette automaticamente in minuscolo il nome del test aggiunto. (nel tuo esempio, Modernizr.isiOS non restituirà mai true).
Dal

3
Basta piccolo avviso: è possibile semplificare return x ? true : falseal return Boolean(x)o semplicementereturn !!x
tibalt


6

Una versione semplificata, facile da estendere.

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

1
Se si desidera anche questo per lavorare su iOS Simulator è possibile utilizzare: navigator.platform.replace(' Simulator', '').
Koraktor,

Ma non funziona, causa['str'].indexOf('string') == -1
tibalt

navigator.platform sarà esattamente 'iPad', 'iPhone' o 'iPod' a meno che il simulatore non sia in esecuzione.
Kory Nunn,

4

Probabilmente vale la pena rispondere che gli iPad che eseguono iOS 13 saranno navigator.platformimpostati su MacIntel, il che significa che dovrai trovare un altro modo per rilevare i dispositivi iPadOS.


3

L'ho scritto un paio d'anni fa ma credo che funzioni ancora:

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

    }

2

Gli user-agent sui dispositivi iOS dicono iPhone o iPad al loro interno. Ho solo filtrato in base a quelle parole chiave.


4
C'è anche da considerare iPod Touch.
Douglas Greenshields

@DouglasGreenshields Correct. Dimenticato quello, ma credo che trasmetta la sua identità anche nel user-agent.
Bryan Naegele,

L'agente utente di Safari Safari non includerà più "iPad" da iPadOS 13.
Jonny il

2

Ove possibile quando si aggiungono i test di Modernizr, è necessario aggiungere un test per una funzionalità, piuttosto che un dispositivo o un sistema operativo. Non c'è niente di sbagliato nell'aggiungere dieci test tutti i test per iPhone se è quello che serve. Alcune cose non possono essere rilevate.

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

Ad esempio, sull'iPhone (non sull'iPad) il video non può essere riprodotto in linea su una pagina Web, si apre a schermo intero. Quindi ho creato un test "no-inpage-video"

È quindi possibile utilizzare questo in CSS (Modernizr aggiunge una classe .no-inpagevideoal <html>tag se il test fallisce)

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

Questo nasconderà il video su iPhone (quello che sto effettivamente facendo in questo caso è mostrare un'immagine alternativa con un clic per riprodurre il video - non voglio che il lettore video predefinito e il pulsante di riproduzione mostrino).


iOS10 ora consente playsinlinequindi di poter utilizzare 'playsInline' in document.createElement('video');come test ora github.com/Modernizr/Modernizr/issues/2077
Simon_Weaver

2

Wow, un sacco di codice complicato da tempo qui. Mantienilo semplice, per favore!

Questo è IMHO veloce, salva e funziona bene:

 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);
  • E 'veloce, perché i controlli regexp l' ^ s posizione della stringa prima piattaforma tarting e si ferma se non c'è un "IP" (veloce rispetto alla ricerca della stringa UA lunga fino alla fine in ogni caso)
  • È più sicuro del controllo UA (supponendo che navigator.platform sia meno probabilmente falsificato)
  • Rileva il simulatore iPhone / iPad


AGGIORNAMENTO: questo non copre iPad in modalità desktop (e quindi iPadOS 13 predefinito).
Va bene per i miei casi d'uso, se non è per te, vedi le risposte di Justin e kikiwora.


iOS = /^(iPhone|iPad|iPod)/.test(navigator.platform);piuttosto che questo farei iOS = /^(iPhone|iPad|iPod)/.test(navigator.userAgent || navigator.vendor || navigator.platform); come misura di fallback perché nel mio caso navigator.platform non ha funzionato, ma farlo come in seguito ha funzionato bene
Coderboi

navigator.platformnon ha funzionato? Allora sei davvero su iOS? Verificare con jeka.info/test/navigator.html . userAgentdà falsi positivi perché alcuni venditori lo fingono per imitare i dispositivi Apple per qualsiasi motivo. vendorrestituisce solo uno Google Inc., Apple Computer, Inc.o niente (in Firefox).
jj

1

Aggiorna leggermente la prima risposta usando un approccio più funzionale.

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

Non funziona nel simulatore mobile di strumenti di sviluppo Brave / Chrome. RicevoMacIntel
sdfsdf il

1

Puoi anche usare includes

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

1

Nessuna delle risposte precedenti qui funziona per tutti i principali browser su tutte le versioni di iOS, incluso iOS 13. Ecco una soluzione che funziona per Safari, Chrome e Firefox per tutte le versioni di 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()));
})();

Tieni presente che questo frammento di codice è stato scritto con priorità sulla leggibilità, non sulla concisione o sulle prestazioni.

Spiegazione:

  • Se il programma utente contiene "iPod | iPhone | iPad", il dispositivo è chiaramente iOS. Altrimenti, continua ...

  • Qualsiasi altro agente utente che non contenga "Macintosh" non è un dispositivo Apple e pertanto non può essere iOS. Altrimenti, è un dispositivo Apple, quindi continua ...

  • Se maxTouchPointsha un valore 1o superiore, il dispositivo Apple ha un touchscreen e quindi deve essere iOS poiché non ci sono Mac con touchscreen (complimenti a kikiwora per menzionarli maxTouchPoints). Nota che maxTouchPointsè undefinedper iOS 12 e versioni precedenti, quindi abbiamo bisogno di una soluzione diversa per quello scenario ...

  • iOS 12 e versioni precedenti hanno una stranezza che non esiste in Mac OS. La stranezza è che la volumeproprietà di un Audioelemento non può essere impostata correttamente su un valore diverso da 1. Questo perché Apple non consente le variazioni di volume Audiosull'elemento per dispositivi iOS, ma per Mac OS. Tale stranezza può essere utilizzata come metodo di fallback finale per distinguere un dispositivo iOS da un dispositivo Mac OS.


-1

Nel mio caso l'agente utente non era abbastanza buono poiché in Ipad l'agente utente era lo stesso di Mac OS, quindi ho dovuto fare un brutto scherzo:

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
}

basta leggere la domanda che dice rilevare iOS, non rilevare mobile
Cybersupernova

-2

Per rilevare la versione iOS, è necessario destrutturare l'agente utente con un codice Javascript come questo:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.