Визначте, чи пристрій iOS


408

Мені цікаво, чи можна виявити, чи працює браузер на iOS, подібно до того, як ви можете виявити функцію виявлення за допомогою Modernizr (хоча це, очевидно, виявлення пристрою, а не виявлення функцій).

Зазвичай я віддаю перевагу виявленню функцій, але мені потрібно з’ясувати, чи пристрій є iOS через те, як вони обробляють відео відповідно до цього питання API YouTube не працює з пристроєм iPad / iPhone / не-Flash


Див. [Що таке рядок користувача-агента iOS 5?] [1] (дублікат?). [1]: stackoverflow.com/questions/7825873 / ...
dejuknow

1
Це виявлення на стороні клієнта чи на сервері?
Дуглас Гріншілдс

Привіт @DouglasGreenshields, це сторона клієнта
SparrwHawk

1
Також не дублікат, я запитую, як це зробити. Я ніколи раніше не використовував нюхання користувача-агента.
SparrwHawk

Відповіді:


821

Виявлення iOS

Я не прихильник нюхання агента User Agent, але ось як би ви це зробили:

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

Ще один спосіб покладається на navigator.platform:

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

iOSбуде trueабоfalse

Чому б не MSStream

Microsoft ввів слово iPhone в IE11, userAgentщоб якось спробувати обдурити Gmail. Тому нам потрібно виключити це. Більше інформації про це тут і тут .

Нижче оновлено IE11 (оновлення userAgentInternet Explorer для Windows Phone 8.1):

Mozilla / 5.0 (мобільний; Windows Phone 8.1; Android 4.0; ARM; Trident / 7.0; Touch; rv: 11.0; IEMobile / 11.0; NOKIA; Lumia 930), як iPhone OS 7_0_3 Mac OS X AppleWebKit / 537 (KHTML, як Gecko) Мобільний сафарі / 537


Легко додайте більше пристроїв, не використовуючи регулярні вирази:

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()буде trueабоfalse

Примітка. І те, navigator.userAgentі navigator.platformінше, і може бути підробленим користувачем або розширенням браузера.


Виявлення версії iOS

Найпоширеніший спосіб виявлення версії iOS - це аналіз її з рядка User Agent . Але є також умовивід виявлення функцій * ;

Ми знаємо факт, який history APIбув представлений в iOS4 - matchMedia APIв iOS5 - webAudio APIв iOS6 - WebSpeech APIв iOS7 і т. Д.

Примітка . Наступний код не є надійним і порушиться, якщо будь-яка з цих функцій HTML5 застаріла в новій версії iOS. Вас попередили!

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
Дякую П'єру - цей код здається більш простим, я просто цікавлюсь, чи можу я просто вказати "iOS", а не потрібно набирати всі окремі iDevices .... якщо ((navigator.userAgent.match (/ iPhone / i)) | | (navigator.userAgent.match (/ iPod / i)) || (navigator.userAgent.match (/ iPad / i))) {// Зроби щось}
SparrwHawk

9
Те, що ви робите у другому фрагменті, - це умовиводи, а не виявлення функцій. Виявлення функцій - це тестування функцій, які ви насправді збираєтесь використовувати, тоді як те, що ви робите, - це тестування функцій, які, як ви знаєте, були введені в певній версії ОС і виводять з них версію ОС. Це крихко, оскільки майбутні версії iOS можуть видалити ці функції.
Тім Даун

23
Це кращий спосіб написати свій чек:var iOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
LandonSchropp

5
Лише зауважте - масив navigator.platform не працює на iPad Simulator, оскільки у ньому є вся фраза "iPad Simulator" у рядку платформи.
Кевін Ньюмен

9
З iOS 13, агент користувача iPad змінив на "Mac OS", наприклад: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15тому цю відповідь потрібно оновити
zvi

38

Після iOS 13 слід виявити подібні пристрої iOS, оскільки iPad не буде розпізнаний як пристрої iOS старими способами (завдяки новим параметрам "настільних ПК", увімкнутим за замовчуванням):

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

Перша умова для iOS <13 або iPhone або iPad з відключеним режимом робочого столу, друга умова для iPadOS 13 у конфігурації за замовчуванням, оскільки він позиціонує себе як Macintosh Intel, але насправді є єдиним Macintosh з мультитач.

Швидше хак, ніж справжнє рішення, але надійно працюйте для мене

PS Як було сказано раніше, вам, ймовірно, слід додати перевірку IE

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

Чому б не використати navigator.userAgentдля цієї перевірки /iPad|iPhone|iPod/.test(navigator.platform)? Схоже, navigator.platformзавжди повертається "MacIntel" для iPhone iOS <= 12
Charis Theo

@CharisTheo Оскільки iPad не знаходиться в користувачіАгент в iOS> = 13
Kzrbill

але ви вже перевіряєте iPad iOS> = 13 під час другої перевірки чи я щось пропускаю?
Charis Theo

navigator.maxTouchPointsне підтримується в iOS, тому перевірка нічого не зробить для вас.
PaulC

@PaulC, ви праві, що maxTouchPoints не визначено для iOS 12 і нижче, але kikiwora знаходиться на правильному шляху, оскільки maxTouchPoints підтримується в iOS 13. Дивіться мою відповідь.
Боб Арлоф

14

Це встановлює змінну _iOSDeviceна true або false

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

3
що робить !! робити?
Патрік

4
Подвійне заперечення @astronought використовується для передачі
булевим

2
@astronought bang bang, you boolean: D
Qback

1
Використовуючи /iPhone|iPod|iPad/.test(navigator.platform)ви можете уникнути!!
lionello

10

Якщо ви використовуєте Modernizr , ви можете додати спеціальний тест для нього.

Не має значення, який режим виявлення ви вирішили використовувати (userAgent, navigator.vendor або navigator.platform), ви завжди можете його згортати для легшого використання пізніше.

//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
Будьте обережні, Modernizr автоматично зменшує малі назви доданого тесту. (у вашому прикладі Modernizr.isiOS ніколи не поверне справжню). Погана поведінка
ліб

3
Просто крихітні зауваження: ви можете спростити return x ? true : falseдо return Boolean(x)або простоreturn !!x
Тибальт


6

Спрощена, проста в розширенні версія.

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

1
Якщо ви хочете , щоб це працювало на IOS Simulator ви можете використовувати: navigator.platform.replace(' Simulator', '').
Корактор

Але це не працює, причина['str'].indexOf('string') == -1
tibalt

navigator.platform буде точно "iPad", "iPhone" або "iPod", якщо тренажер не працює.
Kory Nunn

4

Напевно, варто відповісти, що iPad під керуванням iOS 13 буде navigator.platformвстановлений MacIntel, тобто знадобиться знайти інший спосіб виявлення пристроїв iPadOS.


3

Я написав це пару років тому, але я вважаю, що це все ще працює:

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

Користувачі-користувачі на пристроях iOS кажуть, що в них iPhone або iPad. Я просто фільтрую на основі цих ключових слів.


4
Тут також слід розглянути можливість iPod Touch.
Дуглас Гріншілдс

@DouglasGreenshields Правильно. Забув про це, але я вважаю, що він передає свою ідентичність і в користувальницькому агенті.
Брайан Наегеле

Агент користувача iPad safari більше не включатиме "iPad" від iPadOS 13.
Jonny

2

По можливості, додаючи тести Modernizr, слід додати тест для функції, а не пристрою чи операційної системи. Немає нічого поганого в тому, щоб додати десять тестів на все тестування для iPhone, якщо для цього потрібно. Деякі речі просто неможливо виявити.

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

Наприклад, на iPhone (а не на iPad) відео не можна відтворювати вбудованому на веб-сторінці, воно відкривається на весь екран. Тому я створив тестове "відео без реклами"

Потім ви можете використовувати це в css (Modernizr додає клас .no-inpagevideoдо <html>тегу, якщо тест не вдається)

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

Це приховає відео на iPhone (те, що я насправді роблю в цьому випадку, показує альтернативне зображення з натисканням клавіші onklick для відтворення відео - я просто не хочу показувати відеоплеєр за замовчуванням та кнопку відтворення).


iOS10 тепер дозволяє, playsinlineтому ви можете використовувати 'playsInline' in document.createElement('video');в якості тесту github.com/Modernizr/Modernizr/isissue/2077
Simon_Weaver

2

Ого, тут багато тривалого хитрого коду. Будь ласка, будь ласка!

Цей 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);
  • Це швидко, тому що регулярне вивільнення перевіряє ^ -те позицію затримки ^ рядка платформи і зупиняється, якщо немає «iP» (швидше, ніж пошук довгої рядки UA до кінця)
  • Це безпечніше, ніж перевірка UA (якщо припустити, що навігатор.платформа менше підроблена)
  • Виявляє iPhone / iPad Simulator


ОНОВЛЕННЯ: Це не охоплює iPad у режимі робочого столу (а отже, iPadOS 13 за замовчуванням).
Це добре для моїх юзерів, якщо це не для вас, дивіться відповіді Джастіна та Кіківори.


iOS = /^(iPhone|iPad|iPod)/.test(navigator.platform);а не це я зробив би iOS = /^(iPhone|iPad|iPod)/.test(navigator.userAgent || navigator.vendor || navigator.platform); як резервний захід, тому що в моєму випадку navigator.platform не працював, але робити це так, як пізніше добре працював
Coderboi

navigator.platformне працювало? Ви дійсно тоді на iOS ?. Перевірте за допомогою jeka.info/test/navigator.html . userAgentдає хибні позитивні результати, оскільки деякі постачальники з будь-яких причин підробляють його, щоб імітувати пристрої Apple. vendorпросто повертає або Google Inc., Apple Computer, Inc.або нічого (у Firefox).
jj

1

Трохи оновіть першу відповідь, використовуючи більш функціональний підхід.

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

Не працює в мобільному тренажері Brave / Chrome для розробників. Я отримуюMacIntel
sdfsdf

1

Жоден з попередніх відповідей тут не працює для всіх основних браузерів для всіх версій iOS, включаючи iOS 13. Ось рішення, яке працює для Safari, Chrome і Firefox для всіх версій 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()));
})();

Зауважте, що цей фрагмент коду був написаний з пріоритетом щодо читабельності, а не стислість чи ефективність.

Пояснення:

  • Якщо користувальницький агент містить будь-яку з "iPod | iPhone | iPad", то явно пристрій є iOS. В іншому випадку продовжуйте ...

  • Будь-який інший користувальницький агент, який не містить "Macintosh", не є пристроєм Apple і тому не може бути iOS. Інакше це пристрій Apple, тож продовжуйте ...

  • Якщо він maxTouchPointsмає значення 1або більше, то пристрій Apple має сенсорний екран, і тому він повинен бути iOS, оскільки немає Macs з сенсорними екранами (kudos to kikiwora для згадки maxTouchPoints). Зауважте, що maxTouchPointsце undefinedдля iOS 12 і нижче, тому нам потрібне інше рішення для цього сценарію ...

  • iOS 12 і нижче має вигадку, яка не існує в Mac OS. Придумка полягає в тому, що volumeвластивість Audioелемента не може бути успішно встановлена ​​на будь-яке значення, крім 1. Це відбувається тому, що Apple не дозволяє змінювати гучність Audioелемента для пристроїв iOS, але робить це для Mac OS. Ця химерність може бути використана як остаточний метод резервного відрізнення пристрою iOS від пристрою Mac OS.


0

Ви також можете використовувати includes

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

-1

У моєму випадку користувальницький агент не надто добре оцінювався, оскільки в Ipad користувальницький агент був таким самим, як у Mac OS, тому мені довелося робити неприємну хитрість:

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
}

просто прочитайте питання, в якому сказано, виявити iOS, а не виявити мобільний
Cybersupernova

-2

Щоб виявити версію iOS, потрібно знищити користувальницький агент за допомогою коду Javascript:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.