关于javascript:在未显示正确的用户代理的情况下,如何在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发布之后,我意识到iPad iOS 13上的Safari中的window.navigator.userAgent与MacOS上的相同。 像这样:

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和触摸屏,然后该设备应该是苹果移动设备,但我想知道是否有更好的建议/方法 在Safari iOS 13中检测到正确的设备名称?

1
2
3
4
5
6
7
8
9
10
11
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 / iPad OS设备的最简单方法是:

1
2
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,如Gecko)",我知道的所有平台检测器均未检测到(目前)不能同时用作移动设备和台式机。

因此,由于iPad OS现在称自己为Macintosh,但实际的Mac不支持多点触摸,因此该解决方案非常适合检测iPad OS设备,后者是现有的唯一多点触摸" Macintosh"设备。

附言
另外,您可能希望增加此检查以将IE排除在检测到的iOS设备之外

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


1
2
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"会过滤掉运行Safari的Mac(无论是否触摸屏)。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
 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()

警报(checkMobile.message +" =====>" + checkMobile.isTrue)
shareeditdeleteflag


1
2
3
4
UIWebView *webView = [[UIWebView alloc] init];
NSString *command =[NSString stringWithFormat:@"navigator.userAgent"];
NSString *customUserAgent = [webView stringByEvaluatingJavaScriptFromString:command];
[(WKWebView *)_webView setCustomUserAgent:customUserAgent];