Wykryj, czy urządzeniem jest iOS


408

Zastanawiam się, czy można wykryć, czy przeglądarka działa w systemie iOS, podobnie jak w przypadku funkcji wykrywania za pomocą Modernizr (chociaż jest to oczywiście wykrywanie urządzeń, a nie wykrywanie funkcji).

Zwykle wolałbym zamiast tego wykrywać funkcje, ale muszę dowiedzieć się, czy urządzenie ma system iOS ze względu na sposób, w jaki obsługują filmy zgodnie z tym pytaniem. Interfejs API YouTube nie działa z urządzeniem iPad / iPhone / innym niż Flash


Zobacz [Co to jest ciąg klienta użytkownika iOS 5?] [1] (duplikat?). [1]: stackoverflow.com/questions/7825873/…
— dejuknow

1
Czy to wykrywanie po stronie klienta czy po stronie serwera?
— Douglas Greenshields

Hej @DouglasGreenshields, to jest po stronie klienta
— SparrwHawk

1
Również nie duplikat, pytam, jak to zrobić. Nigdy wcześniej nie używałem wąchania klienta użytkownika.
— SparrwHawk

Odpowiedzi:


821

Wykrywanie iOS

Nie jestem fanem wąchania User User Agent, ale oto jak to zrobić:

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

Innym sposobem jest poleganie na navigator.platform:

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

iOSbędzie albo truealbofalse

Dlaczego nie MSStream

Microsoft wstrzyknął słowo iPhone do IE11 userAgent, aby jakoś oszukać Gmaila. Dlatego musimy to wykluczyć. Więcej informacji na ten temat tutaj i tutaj .

Poniżej znajduje się aktualizacja IE11 (aktualizacja userAgentInternet Explorer dla 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) jak iPhone OS 7_0_3 Mac OS X AppleWebKit / 537 (KHTML, jak Gecko) Mobile Safari / 537


Z łatwością dodawaj więcej urządzeń bez użycia wyrażeń regularnych:

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()będzie albo truealbofalse

Uwaga: Zarówno navigator.userAgenti navigator.platformmogą być sfałszowane przez użytkownika lub rozszerzeniem przeglądarki.


Wykrywanie wersji iOS

Najczęstszym sposobem wykrywania wersji iOS jest parsowanie jej z ciągu Agenta użytkownika . Ale istnieje również wnioskowanie o wykrywaniu funkcji * ;

Wiemy o tym, że history APIzostał wprowadzony w iOS4 - matchMedia APIw iOS5 - webAudio APIw iOS6 - WebSpeech APIw iOS7 itd.

Uwaga: poniższy kod nie jest niezawodny i ulegnie awarii, jeśli którakolwiek z tych funkcji HTML5 będzie przestarzała w nowszej wersji iOS. Zostałeś ostrzeżony!

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
Dzięki Pierre - ten kod wydaje się jednak prostszy, po prostu zastanawiam się, czy mogę po prostu określić „iOS” zamiast wpisywać wszystkie oddzielne iDevices .... if ((navigator.userAgent.match (/ iPhone / i)) | | (navigator.userAgent.match (/ iPod / i)) || (navigator.userAgent.match (/ iPad / i))) {// Zrób coś}
— SparrwHawk

9
Drugim fragmentem zajmuje się wnioskowanie o funkcjach, a nie ich wykrywanie. Wykrywanie funkcji to testowanie funkcji, których faktycznie będziesz używać, podczas gdy to, co robisz, to testowanie funkcji, o których wiesz, że zostały wprowadzone w konkretnej wersji systemu operacyjnego i wnioskowanie na ich podstawie. Jest to kruche, ponieważ przyszłe wersje iOS mogłyby usunąć te funkcje.
— Tim Down

23
Jest to lepszy sposób na napisanie czeku:var iOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
— LandonSchropp

5
Tylko uwaga - tablica navigator.platform nie działa na iPadzie Simulator, ponieważ ma całą frazę „iPad Simulator” w łańcuchu platformy.
— Kevin Newman,

9
Z iOS 13 agent użytkownika iPada zmienił się na „Mac OS”, na przykład: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15więc odpowiedź musi zostać zaktualizowana
— zvi

38

Po iOS 13 powinieneś wykryć takie urządzenia iOS, ponieważ iPad nie będzie wykrywany jako urządzenie iOS na stare sposoby (ze względu na nowe opcje „pulpitu”, domyślnie włączone):

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

Pierwszy warunek dla iOS <13 lub iPhone'a lub iPada z wyłączonym trybem Pulpit, drugi warunek dla iPadOS 13 w domyślnej konfiguracji, ponieważ ustawia się jak Macintosh Intel, ale tak naprawdę jest to jedyny Macintosh z funkcją Multi-Touch.

Raczej hack niż prawdziwe rozwiązanie, ale działaj niezawodnie dla mnie

PS Jak powiedziano wcześniej, prawdopodobnie należy dodać kontrolę IE

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

Dlaczego nie skorzystać z navigator.userAgenttej kontroli /iPad|iPhone|iPod/.test(navigator.platform)? Wygląda na to, że navigator.platformzawsze zwraca „MacIntel” na iPhone'a iOS <= 12
— Charis Theo

@CharisTheo Ponieważ iPad nie jest w userAgent w iOS> = 13
— Kzrbill

ale sprawdzasz już iPada iOS> = 13 w drugim teście, czy coś mi brakuje?
— Charis Theo,

navigator.maxTouchPointsnie jest obsługiwany w iOS, więc czek nie zrobi nic dla ciebie.
— PaulC

@PaulC, masz rację, że maxTouchPoints jest niezdefiniowany dla iOS 12 i niższych, ale kikiwora jest na dobrej drodze, ponieważ maxTouchPoints jest obsługiwany w iOS 13. Zobacz moją odpowiedź.
— Bob Arlof

14

Ustawia zmienną _iOSDevicena true lub false

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

3
co robi !! zrobić?
— Patrick

4
Podwójna negacja @astronought służy do rzucenia na wartość logiczną
— Vitim.us

2
@astronought bang bang, boolean: D
— Qback

1
Za pomocą /iPhone|iPod|iPad/.test(navigator.platform)można uniknąć!!
— lionello

10

Jeśli korzystasz z Modernizr , możesz dodać niestandardowy test.

Nie ma znaczenia, z którego trybu wykrywania zdecydujesz się skorzystać (userAgent, navigator.vendor lub navigator.platform), zawsze możesz go zawinąć, aby ułatwić później.

//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
Bądź ostrożny, Modernizr automatycznie dodaje małe litery do nazwy dodanego testu. (w twoim przykładzie Modernizr.isiOS nigdy nie zwróci wartości true). Złe zachowanie lib w mojej opinii ...
— Cétia,

3
Wystarczy mały uwaga: można uprościć return x ? true : falsedo return Boolean(x)lub po prostureturn !!x
— tibalt


6

Uproszczona, łatwa do rozszerzenia wersja.

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

1
Jeśli chcesz to do pracy na symulatorze iOS można użyć: navigator.platform.replace(' Simulator', '').
— Koraktor,

Ale to nie działa, ponieważ['str'].indexOf('string') == -1
— Tibalt

navigator.platformą będzie dokładnie „iPad”, „iPhone” lub „iPod”, chyba że uruchomiony jest symulator.
— Kory Nunn,

4

Prawdopodobnie warto odpowiedzieć, że iPady z systemem iOS 13 będą navigator.platformustawione na MacIntel, co oznacza, że ​​będziesz musiał znaleźć inny sposób wykrywania urządzeń iPadOS.


3

Napisałem to kilka lat temu, ale wierzę, że nadal działa:

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

Programy klienckie na urządzeniach z iOS mówią w nich iPhone lub iPad. Po prostu filtruję według tych słów kluczowych.


4
Do rozważenia są także iPod Touches.
— Douglas Greenshields

@DouglasGreenshields poprawnie. Zapomniałem o tym, ale wierzę, że przekazuje on również swoją tożsamość w kliencie użytkownika.
— Bryan Naegele

Agent użytkownika iPada Safari nie będzie już zawierał „iPad” z iPada 13.
— Jonny

2

O ile to możliwe, dodając testy Modernizr, należy dodać test funkcji, a nie urządzenia lub systemu operacyjnego. Nie ma nic złego w dodawaniu dziesięciu testów do testowania iPhone'a, jeśli tego właśnie potrzeba. Niektórych rzeczy po prostu nie można wykryć.

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

Na przykład wideo na iPhonie (nie na iPadzie) nie może być odtwarzane bezpośrednio na stronie internetowej, otwiera się pełny ekran. Więc stworzyłem test „wideo bez strony”

Możesz następnie użyć tego w css (Modernizr dodaje klasę .no-inpagevideodo <html>tagu, jeśli test się nie powiedzie)

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

To ukryje wideo na iPhonie (tak naprawdę robię w tym przypadku pokazując alternatywny obraz z kliknięciem, aby odtworzyć wideo - po prostu nie chcę, aby wyświetlał się domyślny odtwarzacz wideo i przycisk odtwarzania).


iOS10 pozwala teraz, playsinlinewięc możesz użyć 'playsInline' in document.createElement('video');jako testu teraz github.com/Modernizr/Modernizr/issues/2077
— Simon_Weaver 30.09.16

2

Wow, dużo długiego, trudnego kodu tutaj. Proszę, zachowaj prostotę!

Ten jest szybki, zapisuj i działa dobrze IMHO:

 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);
  • Jest szybki, ponieważ kontrole regexp ^ s pozycję pierwszego napisu platformy tarting i zatrzymuje się, gdy nie ma „IP” (szybciej niż przeszukując długi ciąg UA do końca tak)
  • Jest bezpieczniejszy niż czek UA (przy założeniu, że platforma navigator.pl prawdopodobnie nie zostanie sfałszowana)
  • Wykrywa iPhone / iPad Simulator


AKTUALIZACJA: Nie dotyczy iPada w trybie pulpitu (a zatem domyślnego iPada 13).
To dobrze dla moich przypadków użycia, jeśli nie jest dla ciebie, zobacz odpowiedzi Justina i kikiwory.


iOS = /^(iPhone|iPad|iPod)/.test(navigator.platform);zamiast tego zrobiłbym to iOS = /^(iPhone|iPad|iPod)/.test(navigator.userAgent || navigator.vendor || navigator.platform); jako rozwiązanie awaryjne, ponieważ w moim przypadku navigator.pl
— Platforma

navigator.platformnie działało? Czy naprawdę jesteś na iOS? Sprawdź na stronie jeka.info/test/navigator.html . userAgentdaje fałszywie pozytywne wyniki, ponieważ niektórzy sprzedawcy podrobili to, aby naśladować urządzenia Apple z jakichkolwiek powodów. vendorpo prostu zwraca albo Google Inc., Apple Computer, Inc.albo nic (Firefox).
— jj

1

Nieznacznie zaktualizuj pierwszą odpowiedź, stosując bardziej funkcjonalne podejście.

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

Nie działa w mobilnym symulatorze narzędzi programistycznych Brave / Chrome. DostajęMacIntel
— sdfsdf

1

Żadna z poprzednich odpowiedzi tutaj nie działa dla wszystkich głównych przeglądarek we wszystkich wersjach iOS, w tym iOS 13. Oto rozwiązanie, które działa w Safari, Chrome i Firefox dla wszystkich wersji 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()));
})();

Pamiętaj, że ten fragment kodu został napisany z myślą o czytelności, a nie zwięzłości lub wydajności.

Wyjaśnienie:

  • Jeśli klient użytkownika zawiera którykolwiek z „iPod | iPhone | iPad”, to oczywiście urządzenie to iOS. W przeciwnym razie kontynuuj ...

  • Każdy inny klient użytkownika, który nie zawiera „Macintosh”, nie jest urządzeniem Apple i dlatego nie może być iOS. W przeciwnym razie jest to urządzenie Apple, więc kontynuuj ...

  • Jeśli maxTouchPointsma wartość równą 1lub większą, to urządzenie Apple ma ekran dotykowy i dlatego musi być systemem iOS, ponieważ nie ma komputerów Mac z ekranami dotykowymi (podziękowania dla kikiwory za wzmiankę maxTouchPoints). Pamiętaj, że dotyczy maxTouchPointsto undefinediOS 12 i niższych, dlatego potrzebujemy innego rozwiązania dla tego scenariusza ...

  • iOS 12 i poniżej mają dziwactwo, które nie istnieje w Mac OS. Dziwactwo polega na tym, że volumewłaściwości Audioelementu nie można pomyślnie ustawić na żadną inną wartość niż 1. Wynika to z faktu, że Apple nie zezwala na zmiany głośności w Audioelemencie dla urządzeń z systemem iOS, ale zezwala na system Mac OS. To dziwactwo może być wykorzystane jako ostateczna metoda zastępcza dla odróżnienia urządzenia iOS od urządzenia Mac OS.


0

Możesz także użyć includes

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

-1

W moim przypadku agent użytkownika nie był wystarczająco dobry, ponieważ na iPadzie agent użytkownika był taki sam jak w Mac OS, dlatego musiałem zrobić paskudną sztuczkę:

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
}

po prostu przeczytaj pytanie: wykryj iOS, a nie wykryj telefon komórkowy
— Cybersupernova

-2

Aby wykryć wersję iOS, należy zniszczyć agenta użytkownika za pomocą kodu JavaScript takiego:

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.