ChatGPT解决这个技术问题 Extra ChatGPT

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

After Apple's iOS 13 release, I realized window.navigator.userAgent in Safari on iPad iOS 13 is same as on MacOS. Something like this:

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

As you see, it's a wrong user-agent for iPad and there is no way to detect if the current device is an iDevice.

After an initial research, I found a workaround for it:

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.

But I cannot ask each user to do this setting change for each device. So I tried to find another way and ended up by writing the following code which checks if it's Safari, macOS, and touch-screen then the device should be an apple mobile device, but I'm wondering is there any better suggestion/way to detect the correct device name in 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;
};
I am stuck with same issue but i need to check on Server side so I can show mobile side menu instead of full website menu on Safari iOS13. could you help me with this please? stackoverflow.com/questions/58344491/…
Why do you need to know this? Generally browser sniffing is a bad idea. Instead you should be writing your application so that it works on all browsers equally. If you need to disinguish between abilities of browsers then look into feature detection.
OP can you please mark @kikiwora's answer as accepted
OP, could you mark @kikiwora's answer as accepted, if it actually soved your problem? If not, please let us know if you ran into other issues with this solution.

B
BuZZ-dEE

Indeed, while option change in Settings may be a good solution for the user, as a developer you can't rely on that. It is as weird as to ask the user to not to use dark mode cause your app doesn't support it instead of opt-out of it using plist.

As for me, the most simple way to detect iOS / iPad OS device now:

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

The first condition is old-fashioned and works with previous versions, while the second condition works for iPad OS 13 which now identifies itself as:

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

which by all platform detectors I know is not detected (for now) neither as mobile nor desktop.

So since iPad OS now calls itself Macintosh, but real macs have no multi-touch support, this solution is ideal to detect iPad OS devices which are the only multi-touch "Macintosh" devices in existence.

P.S. Also, you may want to augment this checkup for IE exclusion from being detected as an iOS device

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

thanks that is useful for clientside. could you please help how to detect in razor syntax on server side when page is rendering. badly stuck with this problem. stackoverflow.com/questions/58344491/…
I’m not proficient with a razor, sorry 🤷🏻‍♂️ Also, I don’t think that’s possible on the server side since iPad sends Macintosh header to server - iPad now meant to work like desktop in web and we should not intervene in this behavior
This solution designed for Safari in the first place. It's weird that Mozilla site lists this JS method as unsupported in Safari. It definitely works on all of my Apple devices (laptop, tablet and phone) But indeed, the downside of this method is very fragile from a long-term use perspective. Especially if touch-enabled macs will be available. The thing is, as I said, that new Safari is meant to be like that - it was designed to be detected as a desktop to provide more features for users, since modern sites ofter not so functional mobile versions instead, forcing users to use them.
Thanks for this solution. This fixed what I needed it for. Although it's not the best long-term, it's a good bandaid fix until either Apple comes out with Touchscreen computers or they get their crap together and name their devices correctly!
⚠️ Just as a notice - this code may become obsolete soon, since now we have an Apple Silicone-based Macs & a hint regarding Touch-base Macs has been found in the App Store animations, and even publicly displayed for some time.
G
GuyC
const isIOS = !!(/iPad|iPhone|iPod/.test(navigator.platform)
  || (navigator.platform === "MacIntel" && typeof navigator.standalone !== "undefined"))

As an alternative to the accepted answer, I found you can use the navigator.standalone param. It's non-standard and used only on iOS Safari at present:

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

When combined with navigator.platform === "MacIntel" iPad's are the only devices that define this property, therefore typeof navigator.standalone !== "undefined" filters out Macs running Safari (touchscreen or not).


shouldn't it be isIpadSafari = ?
@kofifus the first part of the OR condition tests for iPad//iPhone/iPod in the platform string. The second part is the iOS 13 iPad so it's not just looking for iPads running Safari
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

This will detect an iPhone also as iPad as the deviceWidth > 750.
@RogerFar I think that's less of a sacrifice than categorizing touch screen iBooks or iMacs as mobile devices. Seems like people are completely lost in the forest with this issue and since the Safari can lie now the only way to sort out the issue is to test for some feature like this snippet does. If you like you can add more code to test width and sophisticate it further as you like.
i
itlijunjie
UIWebView *webView = [[UIWebView alloc] init];
NSString *command =[NSString stringWithFormat:@"navigator.userAgent"];
NSString *customUserAgent = [webView stringByEvaluatingJavaScriptFromString:command];
[(WKWebView *)_webView setCustomUserAgent:customUserAgent];

Please provide some explanation for your answer.
Wrong language entirely.