如何在 iOS 13 上的 Safari 中检测设备名称,同时它没有显示正确的用户代理?

How to detect device name in Safari on iOS 13 while it doesn't show the correct user agent?

Apple iOS 13 发布后,我发现 window.navigator.userAgent 在 Safari 上 iPad iOS 13 与苹果系统。像这样:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15

如您所见,它是 iPad 的错误用户代理,无法检测当前设备是否为 iDevice。


经过初步研究,我找到了解决方法:

Go to Settings -> Safari -> Request Desktop Website -> All websites. You notice "All websites" is enabled by default. If you disable it and get window.navigator.userAgent the correct user agent is now displayed.

但我不能要求每个用户为每个设备做这个设置更改。所以我试图找到另一种方法,最后写了 下面的代码来检查它是否是 Safari、macOS 和触摸屏,然后设备应该是苹果移动设备 ,但是我'我想知道是否有更好的 suggestion/way 来检测 Safari 中正确的设备名称 iOS 13?

detectOs = function(){
   //returns OS name, like "mac"
};

//is Safari on an apple touch-screen device
isSafariInIdevice = function(){
   if (/Safari[\/\s](\d+\.\d+)/.test(windows.navigator.userAgent)) {
      return 'ontouchstart' in window && detectOs() === "mac";      
   }
   return false;
};

的确,虽然“设置”中的选项更改对用户来说可能是一个很好的解决方案,但作为开发人员,您不能依赖它。这就像要求用户不要使用暗模式一样奇怪,因为你的应用程序不支持它而不是使用 plist 选择退出它。

对于我来说,现在检测iOS/iPadOS设备最简单的方法:

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

第一个条件是老式的,适用于以前的版本, 而第二个条件适用于 iPad OS 13,它现在将自己标识为:

"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko)"

我所知道的所有平台检测器都没有检测到(目前)既不是移动端也不是桌面端。

因此,由于 iPad OS 现在称自己为 Macintosh,但真正的 mac 不支持多点触控,此解决方案非常适合检测 iPad OS 设备是现存唯一的多点触控“Macintosh”设备。

P.S. 此外,您可能希望增加此检查以排除 IE 被检测为 iOS 设备

let isIOS = (/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&
!window.MSStream
UIWebView *webView = [[UIWebView alloc] init];
NSString *command =[NSString stringWithFormat:@"navigator.userAgent"];
NSString *customUserAgent = [webView stringByEvaluatingJavaScriptFromString:command];
[(WKWebView *)_webView setCustomUserAgent:customUserAgent];
     function mobileDetect() {


    var agent = window.navigator.userAgent;
    var d = document;
    var e = d.documentElement;
    var g = d.getElementsByTagName('body')[0];
    var deviceWidth = window.innerWidth || e.clientWidth || g.clientWidth;

    // Chrome
    IsChromeApp = window.chrome && chrome.app && chrome.app.runtime;

    // iPhone
    IsIPhone = agent.match(/iPhone/i) != null;

    // iPad up to IOS12
    IsIPad = (agent.match(/iPad/i) != null) || ((agent.match(/iPhone/i) != null) && (deviceWidth > 750)); // iPadPro when run with no launch screen can have error in userAgent reporting as an iPhone rather than an iPad. iPadPro width portrait 768, iPhone6 plus 414x736 but would probably always report 414 on app startup

    if (IsIPad) IsIPhone = false;

    // iPad from IOS13
    var macApp = agent.match(/Macintosh/i) != null;
    if (macApp) {
        // need to distinguish between Macbook and iPad
        var canvas = document.createElement("canvas");
        if (canvas != null) {
            var context = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
            if (context) {
                var info = context.getExtension("WEBGL_debug_renderer_info");
                if (info) {
                    var renderer = context.getParameter(info.UNMASKED_RENDERER_WEBGL);
                    if (renderer.indexOf("Apple") != -1) IsIPad = true;
                }
                ;
            }
            ;
        }
        ;
    }
    ;

    // IOS
    IsIOSApp = IsIPad || IsIPhone;

    // Android
    IsAndroid = agent.match(/Android/i) != null;
    IsAndroidPhone = IsAndroid && deviceWidth <= 960;
    IsAndroidTablet = IsAndroid && !IsAndroidPhone;



    message = ""


    if (IsIPhone) {

        message = "Device is IsIPhone"


    }
    else if (IsIPad) {

        message = "Device is ipad"

    } else if (IsAndroidTablet || IsAndroidPhone || IsAndroid) {

        message = "Device is Android"


    } else {

        message = "Device is Mac ||  Windows Desktop"

    }


    return {

        message: message,

        isTrue: IsIOSApp || IsAndroid || IsAndroidTablet || IsAndroidPhone

    }

}



const checkMobile = mobileDetect()

alert(checkMobile.message + "  =====>  " + checkMobile.isTrue)
shareeditdeleteflag
const isIOS = !!(/iPad|iPhone|iPod/.test(navigator.platform)
  || (navigator.platform === "MacIntel" && typeof navigator.standalone !== "undefined"))

作为已接受答案的替代方案,我发现您可以使用 navigator.standalone 参数。它是非标准的,目前仅在 iOS Safari 上使用:

Navigator.standalone

Returns a boolean indicating whether the browser is running in standalone mode. Available on Apple's iOS Safari only.

navigator.platform === "MacIntel" 结合时,iPad 是唯一定义此 属性 的设备,因此 typeof navigator.standalone !== "undefined" 过滤掉 Mac 运行 Safari(触摸屏或不)。