ChatGPT解决这个技术问题 Extra ChatGPT

如何在 iOS 13 上的 Safari 中检测设备名称而不显示正确的用户代理?

在 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。

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

转到设置 -> Safari -> 请求桌面网站 -> 所有网站。您注意到默认情况下启用“所有网站”。如果您禁用它并获取 window.navigator.userAgent,则现在会显示正确的用户代理。

但我不能要求每个用户为每个设备进行此设置更改。所以我试图找到另一种方法,最后编写了以下代码来检查它是否是 Safari、macOS 和触摸屏,那么该设备应该是苹果移动设备,但我想知道有没有更好的建议/方法在 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;
};
我遇到了同样的问题,但我需要检查服务器端,以便我可以在 Safari iOS13 上显示移动端菜单而不是完整的网站菜单。你能帮我解决这个问题吗? stackoverflow.com/questions/58344491/…
为什么你需要知道这个?通常浏览器嗅探是一个坏主意。相反,您应该编写您的应用程序,以便它可以平等地在所有浏览器上运行。如果您需要区分浏览器的功能,请查看 feature detection
OP,您能否将@kikiwora 的答案标记为已接受
OP,如果它确实解决了您的问题,您能否将@kikiwora 的答案标记为已接受?如果没有,请让我们知道您是否遇到此解决方案的其他问题。

B
BuZZ-dEE

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

至于我,现在检测 iOS / iPad OS 设备的最简单方法:

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”设备。

PS 此外,您可能希望增加此检查以防止 IE 被检测为 iOS 设备

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

谢谢这对客户端有用。您能否帮助如何在页面呈现时在服务器端检测剃刀语法。严重卡住了这个问题。 stackoverflow.com/questions/58344491/…
我不精通剃须刀,对不起🤷🏻‍♂️另外,我认为这在服务器端是不可能的,因为 iPad 将 Macintosh 标头发送到服务器 - iPad 现在意味着在网络中像桌面一样工作,我们不应该干预这种行为
该解决方案最初是为 Safari 设计的。奇怪的是,Mozilla 网站将此 JS 方法列为 Safari 不支持。它绝对适用于我所有的 Apple 设备(笔记本电脑、平板电脑和手机),但事实上,从长期使用的角度来看,这种方法的缺点是非常脆弱的。尤其是当支持触控的 Mac 可用时。问题是,正如我所说,新的 Safari 本来就是这样的——它被设计为被检测为桌面,为用户提供更多功能,因为现代网站通常不是功能强大的移动版本,而是迫使用户使用它们.
感谢您提供此解决方案。这解决了我需要它的问题。虽然这不是最好的长期方案,但它是一个很好的创可贴解决方案,直到 Apple 推出触摸屏电脑,或者他们把他们的废话放在一起并正确命名他们的设备!
⚠️ 就像一个通知 - 此代码可能很快就会过时,因为现在我们有一个基于 Apple Silicone 的 Mac 并且在 App Store 动画中发现了关于基于 Touch 的 Mac 的提示,甚至公开展示了一段时间。
G
GuyC
const isIOS = !!(/iPad|iPhone|iPod/.test(navigator.platform)
  || (navigator.platform === "MacIntel" && typeof navigator.standalone !== "undefined"))

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

Navigator.standalone 返回一个布尔值,指示浏览器是否在独立模式下运行。仅适用于 Apple 的 iOS Safari。

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


不应该是 isIpadSafari = 吗?
@kofifus 平台字符串中 iPad//iPhone/iPod 的 OR 条件测试的第一部分。第二部分是 iOS 13 iPad,所以它不只是在寻找运行 Safari 的 iPad
B
BuZZ-dEE
     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

这将把 iPhone 也检测为 iPad,因为 deviceWidth > 750。
@RogerFar 我认为这比将触摸屏 iBooks 或 iMacs 归类为移动设备要少。似乎人们在这个问题上完全迷失了方向,因为 Safari 现在可以说谎,解决这个问题的唯一方法是测试这个片段的某些功能。如果您愿意,可以添加更多代码来测试宽度并根据需要进一步完善它。
i
itlijunjie
UIWebView *webView = [[UIWebView alloc] init];
NSString *command =[NSString stringWithFormat:@"navigator.userAgent"];
NSString *customUserAgent = [webView stringByEvaluatingJavaScriptFromString:command];
[(WKWebView *)_webView setCustomUserAgent:customUserAgent];

请为您的答案提供一些解释。
完全错误的语言。