Mendeteksi apakah perangkat iOS

408

Saya bertanya-tanya apakah mungkin untuk mendeteksi apakah browser berjalan di iOS, mirip dengan bagaimana Anda dapat mendeteksi fitur dengan Modernizr (meskipun ini jelas deteksi perangkat daripada deteksi fitur).

Biasanya saya lebih suka deteksi fitur, tetapi saya perlu mencari tahu apakah suatu perangkat iOS karena cara mereka menangani video sesuai pertanyaan ini, YouTube API tidak bekerja dengan perangkat iPad / iPhone / non-Flash

SparrwHawk
sumber
Lihat [Apa string agen pengguna iOS 5?] [1] (duplikat?). [1]: stackoverflow.com/questions/7825873/…
dejuknow
1
Apakah deteksi sisi klien atau sisi server ini?
Douglas Greenshields
Hei @DouglasGreenshields, ini adalah sisi klien
SparrwHawk
1
Juga, bukan duplikat, saya bertanya bagaimana melakukannya. Saya belum pernah menggunakan agen-pengguna mengendus sebelumnya.
SparrwHawk

Jawaban:

821

Mendeteksi iOS

Saya bukan penggemar Agen Pengguna mengendus, tetapi di sini adalah bagaimana Anda akan melakukannya:

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

Cara lain mengandalkan navigator.platform:

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

iOSakan menjadi trueataufalse

Kenapa tidak MSStream

Microsoft menyuntikkan kata iPhone di IE11 userAgentuntuk mencoba menipu Gmail. Karena itu kita perlu mengecualikannya. Info lebih lanjut tentang ini di sini dan di sini .

Di bawah ini adalah pembaruan IE11 userAgent( Pembaruan Internet Explorer untuk 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) seperti iPhone OS 7_0_3 Mac OS X AppleWebKit / 537 (KHTML, seperti Gecko) Mobile Safari / 537


Menambahkan lebih banyak perangkat dengan mudah, tanpa menggunakan Ekspresi Reguler:

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()akan menjadi trueataufalse

Catatan: Keduanya navigator.userAgentdan navigator.platformdapat dipalsukan oleh pengguna atau ekstensi browser.


Mendeteksi versi iOS

Cara paling umum untuk mendeteksi versi iOS adalah dengan menguraikannya dari string Agen Pengguna . Tetapi ada juga inferensi deteksi fitur * ;

Kami tahu fakta yang history APIdiperkenalkan di iOS4 - matchMedia APIdi iOS5 - webAudio APIdi iOS6 -WebSpeech API di iOS7 dan seterusnya ..

Catatan: Kode berikut ini tidak dapat diandalkan dan akan rusak jika salah satu fitur HTML5 ini tidak digunakan dalam versi iOS yang lebih baru. Anda telah diperingatkan!

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
sumber
2
Terima kasih Pierre - kode ini tampaknya lebih sederhana, saya hanya ingin tahu apakah saya bisa menentukan 'iOS' daripada harus mengetik semua iDevices terpisah .... if ((navigator.userAgent.match (/ iPhone / i)) | | (navigator.userAgent.match (/ iPod / i)) || (navigator.userAgent.match (/ iPad / i))) {// Lakukan sesuatu}
SparrwHawk
9
Apa yang Anda lakukan di cuplikan kedua adalah inferensi fitur, bukan deteksi fitur. Deteksi fitur adalah fitur pengujian yang benar-benar akan Anda gunakan, sedangkan yang Anda lakukan adalah menguji fitur yang kebetulan Anda ketahui diperkenalkan di versi OS tertentu dan menyimpulkan versi OS dari mereka. Ini rapuh karena versi iOS masa depan dapat menghapus fitur-fitur ini.
Tim Down
23
Ini adalah cara yang lebih baik untuk menulis cek Anda:var iOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
LandonSchropp
5
Hanya sebuah catatan - array navigator.platform tidak berfungsi pada iPad Simulator karena memiliki seluruh frase "iPad Simulator" dalam string platform.
Kevin Newman
9
Dari iOS 13 agen pengguna iPad telah berubah menjadi "Mac OS", misalnya: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15jadi jawaban ini perlu diperbarui
zvi
38

Setelah iOS 13 Anda harus mendeteksi perangkat iOS seperti ini, karena iPad tidak akan terdeteksi sebagai perangkat iOS dengan cara lama (karena opsi "desktop" baru, diaktifkan secara default):

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

Kondisi pertama untuk iOS <13 atau iPhone atau iPad dengan mode Desktop yang dinonaktifkan, kondisi kedua untuk iPadOS 13 dalam konfigurasi default, karena posisinya sendiri seperti Macintosh Intel, tetapi sebenarnya adalah satu-satunya Macintosh dengan multi-touch.

Alih-alih meretas daripada solusi nyata, tetapi bekerja dengan andal bagi saya

PS Seperti yang dikatakan sebelumnya, Anda mungkin harus menambahkan pemeriksaan IE

let isIOS = (/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&
!window.MSStream
kikiwora
sumber
Mengapa tidak menggunakan navigator.userAgentcek ini /iPad|iPhone|iPod/.test(navigator.platform)? Tampaknya navigator.platformselalu mengembalikan 'MacIntel' untuk iPhone iOS <= 12
Charis Theo
@CharisTheo Karena iPad tidak ada di UserAgent di iOS> = 13
Kzrbill
tetapi Anda sudah memeriksa iPad iOS> = 13 pada pemeriksaan kedua atau apakah saya kehilangan sesuatu?
Charis Theo
navigator.maxTouchPointstidak didukung di iOS, sehingga pemeriksaan tidak akan melakukan apa pun untuk Anda.
PaulC
@ PaulC, Anda benar karena maxTouchPoints tidak terdefinisi untuk iOS 12 dan di bawah, tetapi kikiwora berada di jalur yang benar karena maxTouchPoints didukung di iOS 13. Lihat jawaban saya.
Bob Arlof
14

Ini mengatur variabel _iOSDeviceke true atau false

_iOSDevice = !!navigator.platform.match(/iPhone|iPod|iPad/);
Vitim.us
sumber
3
apa ya !! melakukan?
patrick
4
@ negronought double negation digunakan untuk melakukan cast ke boolean
Vitim.us
2
@astronought bang bang, kau boolean: D
Qback
1
Menggunakan /iPhone|iPod|iPad/.test(navigator.platform)Anda dapat menghindari!!
lionello
10

Jika Anda menggunakan Modernizr , Anda dapat menambahkan tes khusus untuk itu.

Tidak masalah mode deteksi mana yang Anda putuskan untuk digunakan (userAgent, navigator.vendor atau navigator.platform), Anda selalu dapat membungkusnya untuk penggunaan yang lebih mudah nanti.

//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
sumber
2
Hati-hati, Modernizr secara otomatis mengurangi nama tes yang ditambahkan. (dalam contoh Anda, Modernizr.isiOS tidak akan pernah mengembalikan true). Perilaku buruk lib dalam pandangan saya ...
Cétia
3
Pemberitahuan hanya kecil: Anda dapat menyederhanakan return x ? true : falseuntuk return Boolean(x)atau hanyareturn !!x
tibalt
6

Versi yang disederhanakan dan mudah diperluas.

var iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;
Kory Nunn
sumber
1
Jika Anda juga ingin ini bekerja pada iOS Simulator Anda dapat menggunakan: navigator.platform.replace(' Simulator', '').
Koraktor
Tapi itu tidak berhasil, sebab['str'].indexOf('string') == -1
tibalt
navigator.platform akan persis 'iPad', 'iPhone' atau 'iPod' kecuali jika simulator sedang berjalan.
Kory Nunn
4

Mungkin patut untuk menjawab bahwa iPad yang menjalankan iOS 13 akan navigator.platformdiatur ke MacIntel, yang berarti Anda harus mencari cara lain untuk mendeteksi perangkat iPadOS.

Justin Searls
sumber
3

Saya menulis ini beberapa tahun yang lalu tetapi saya percaya itu masih berfungsi:

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 Benin
sumber
2

Agen-pengguna pada perangkat iOS mengatakan iPhone atau iPad di dalamnya. Saya hanya memfilter berdasarkan kata kunci tersebut.

Bryan Naegele
sumber
4
Ada juga iPod Touch untuk dipertimbangkan.
Douglas Greenshields
@DouglasGreenshields Benar. Lupa tentang yang itu tapi saya percaya itu mentransmisikan identitasnya di agen-pengguna, juga.
Bryan Naegele
Agen pengguna iPad safari tidak akan lagi menyertakan "iPad" dari iPadOS 13.
Jonny
2

Sedapat mungkin ketika menambahkan tes Modernizr Anda harus menambahkan tes untuk fitur, bukan perangkat atau sistem operasi. Tidak ada yang salah dengan menambahkan sepuluh tes semua pengujian untuk iPhone jika itu yang diperlukan. Beberapa hal tidak dapat dideteksi fitur.

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

Misalnya pada iPhone (bukan iPad) video tidak dapat diputar inline pada halaman web, itu membuka layar penuh. Jadi saya membuat tes 'no-inpage-video'

Anda kemudian dapat menggunakan ini di css (Modernizr menambahkan kelas .no-inpagevideoke <html>tag jika tes gagal)

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

Ini akan menyembunyikan video di iPhone (yang sebenarnya saya lakukan dalam kasus ini adalah menampilkan gambar alternatif dengan onclick untuk memutar video - Saya hanya tidak ingin pemutar video dan tombol putar tampil).

Simon_Weaver
sumber
iOS10 sekarang memungkinkan untuk playsinlinesehingga Anda dapat menggunakan 'playsInline' in document.createElement('video');sebagai tes sekarang github.com/Modernizr/Modernizr/issues/2077
Simon_Weaver
2

Wow, banyak kode rumit gondrong di sini. Tolong sederhana saja!

Yang ini IMHO cepat, simpan, dan bekerja dengan baik:

 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);
  • Cepat karena regexp memeriksa ^ s posisi platform string pertama tarting dan berhenti jika tidak ada "iP" (lebih cepat dari mencari UA string panjang sampai akhir pula)
  • Ini lebih aman daripada pemeriksaan UA (dengan asumsi navigator.platform cenderung dipalsukan)
  • Mendeteksi Simulator iPhone / iPad


UPDATE: Ini tidak mencakup iPad dalam mode desktop (dan karenanya iPadOS 13 default).
Itu bagus untuk penggunaan saya, jika ini bukan untuk Anda, lihat jawaban Justin dan kikiwora.

jj
sumber
iOS = /^(iPhone|iPad|iPod)/.test(navigator.platform);daripada ini saya akan lakukan iOS = /^(iPhone|iPad|iPod)/.test(navigator.userAgent || navigator.vendor || navigator.platform); sebagai ukuran mundur karena cuz navigator.platform saya tidak bekerja, tetapi melakukannya seperti kemudian bekerja dengan baik
Coderboi
navigator.platformtidak bekerja? Apakah Anda benar-benar menggunakan iOS? Periksa dengan jeka.info/test/navigator.html . userAgentmemberikan positif palsu karena beberapa vendor memalsukannya untuk meniru perangkat Apple dengan alasan apa pun. vendorhanya kembali baik Google Inc., Apple Computer, Inc.atau tidak ada (di Firefox).
jj
1

Perbarui sedikit jawaban pertama menggunakan pendekatan yang lebih fungsional.

    const isIOS = [
      'iPad Simulator',
      'iPhone Simulator',
      'iPod Simulator',
      'iPad',
      'iPhone',
      'iPod',
    ].indexOf(navigator.platform) !== -1;
Sten Muchow
sumber
Tidak berfungsi di simulator seluler alat Berani / Chrome dev. Saya mendapatkanMacIntel
sdfsdf
1

Anda juga bisa menggunakan includes

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

Tidak ada jawaban sebelumnya di sini yang berfungsi untuk semua browser utama di semua versi iOS, termasuk iOS 13. Ini adalah solusi yang berfungsi untuk Safari, Chrome dan Firefox untuk semua versi 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()));
})();

Perhatikan bahwa cuplikan kode ini ditulis dengan prioritas pada keterbacaan, bukan keringkasan atau kinerja.

Penjelasan:

  • Jika agen pengguna berisi "iPod | iPhone | iPad" maka jelas perangkatnya adalah iOS. Kalau tidak, lanjutkan ...

  • Agen pengguna lain apa pun yang tidak mengandung "Macintosh" bukan perangkat Apple dan karenanya tidak bisa iOS. Kalau tidak, itu adalah perangkat Apple, jadi lanjutkan ...

  • Jika maxTouchPointsmemiliki nilai 1atau lebih besar maka perangkat Apple memiliki layar sentuh dan karenanya harus iOS karena tidak ada Mac dengan layar sentuh (kudos to kikiwora untuk menyebutkan maxTouchPoints). Perhatikan bahwa maxTouchPointsadalah undefineduntuk iOS 12 dan di bawah, jadi kita perlu solusi yang berbeda untuk skenario yang ...

  • iOS 12 dan di bawahnya memiliki kekhasan yang tidak ada di Mac OS. Kekhasannya adalah bahwa volumeproperti Audioelemen tidak dapat berhasil diatur ke nilai apa pun selain 1. Ini karena Apple tidak mengizinkan perubahan volume pada Audioelemen untuk perangkat iOS, tetapi untuk Mac OS. Kekhasan itu dapat digunakan sebagai metode fallback akhir untuk membedakan perangkat iOS dari perangkat Mac OS.

Bob Arlof
sumber
-1

Dalam kasus saya agen pengguna tidak cukup baik karena di iPad agen pengguna sama dengan di Mac OS, oleh karena itu saya harus melakukan trik jahat:

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é
sumber
baca saja pertanyaan yang katanya mendeteksi iOS, bukan mendeteksi ponsel
Cybersupernova
-2

Untuk mendeteksi versi iOS, kita harus menghancurkan agen pengguna dengan kode Javascript seperti ini:

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

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

Mithun Sreedharan
sumber