确定用户是否从移动 Safari 导航

发布于 2024-09-05 03:35:00 字数 800 浏览 18 评论 0原文

我有一个应用程序,我想根据用户的导航位置将用户重定向到不同的页面。

如果从 Web Clip 导航,请勿重定向。 如果从移动 Safari 导航,请重定向到 safari.aspx。 如果从其他任何地方导航,请重定向到 unavailable.aspx

我能够使用 iPhone WebApps,有没有办法检测它是如何加载的?主屏幕与 Safari? 来确定用户是否从网络剪辑进行导航,但我无法确定用户是否从 iPhone 或 iPod 上的移动 Safari 进行导航。

这是我所拥有的:

if (window.navigator.standalone) {
    // user navigated from web clip, don't redirect
}
else if (/*logic for mobile Safari*/) {
    //user navigated from mobile Safari, redirect to safari page
    window.location = "safari.aspx";
}
else {
    //user navigated from some other browser, redirect to unavailable page
    window.location = "unavailable.aspx";
}

I have an app, and I'd like to redirect the users to different pages based on where they are navigating from.

If navigating from web clip, do not redirect.
If navigating from mobile Safari, redirect to safari.aspx.
If navigating from anywhere else, redirect to unavailable.aspx

I was able to use iPhone WebApps, is there a way to detect how it was loaded? Home Screen vs Safari? to determine if the user was navigating from a web clip, but I'm having trouble determining if the user navigated from mobile Safari on an iPhone or iPod.

Here's what I have:

if (window.navigator.standalone) {
    // user navigated from web clip, don't redirect
}
else if (/*logic for mobile Safari*/) {
    //user navigated from mobile Safari, redirect to safari page
    window.location = "safari.aspx";
}
else {
    //user navigated from some other browser, redirect to unavailable page
    window.location = "unavailable.aspx";
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

陌若浮生 2024-09-12 03:35:00

请参阅 https://developer.chrome.com/multidevice/user-agent#chrome_for_ios_user_agent - iOS 上的 Safari 和 iOS 上的 Chrome 的用户代理字符串非常相似:

Chrome

Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit /534.46.0(KHTML,如 Gecko)CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3

Safari

Mozilla/5.0(iPhone;U;CPU 类似 Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543 Safari/419.3

看起来这里最好的方法是首先按照其他答案的建议检查 iOS,然后进行过滤使 Safari UA 独一无二的东西,我建议最好通过“是 AppleWebKit 而不是 CriOS”来实现:

var ua = window.navigator.userAgent;
var iOS = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i);
var webkit = !!ua.match(/WebKit/i);
var iOSSafari = iOS && webkit && !ua.match(/CriOS/i);

See https://developer.chrome.com/multidevice/user-agent#chrome_for_ios_user_agent - the user agent strings for Safari on iOS and for Chrome on iOS are inconveniently similar:

Chrome

Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3

Safari

Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543 Safari/419.3

Looks like the best approach here is to first of all check for iOS as other answers have suggested and then filter on the stuff that makes the Safari UA unique, which I would suggest is best accomplished with "is AppleWebKit and is not CriOS":

var ua = window.navigator.userAgent;
var iOS = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i);
var webkit = !!ua.match(/WebKit/i);
var iOSSafari = iOS && webkit && !ua.match(/CriOS/i);
夜巴黎 2024-09-12 03:35:00

更新:这是一个非常旧的答案,我无法删除它,因为答案已被接受。请查看下面不知情的答案以获得更好的解决方案。


您应该能够检查 用户代理 字符串中的“iPad”或“iPhone”子字符串:

var userAgent = window.navigator.userAgent;

if (userAgent.match(/iPad/i) || userAgent.match(/iPhone/i)) {
   // iPad or iPhone
}
else {
   // Anything else
}

UPDATE: This is a very old answer and I cannot delete it because the answer is accepted. Check unwitting's answer below for a better solution.


You should be able to check for the "iPad" or "iPhone" substring in the user agent string:

var userAgent = window.navigator.userAgent;

if (userAgent.match(/iPad/i) || userAgent.match(/iPhone/i)) {
   // iPad or iPhone
}
else {
   // Anything else
}
酒绊 2024-09-12 03:35:00

最佳实践是:

function isMobileSafari() {
    return navigator.userAgent.match(/(iPod|iPhone|iPad)/) && navigator.userAgent.match(/AppleWebKit/)
}

best practice is:

function isMobileSafari() {
    return navigator.userAgent.match(/(iPod|iPhone|iPad)/) && navigator.userAgent.match(/AppleWebKit/)
}
会傲 2024-09-12 03:35:00

合并所有答案和评论。
这就是结果。

function iOSSafari(userAgent) {
    return /iP(ad|od|hone)/i.test(userAgent) &&
      /WebKit/i.test(userAgent) &&
      !(/(CriOS|FxiOS|OPiOS|mercury)/i.test(userAgent));
}


// Usage:
// if iOSSafari(window.navigator.userAgent) { /* iOS Safari code here */ }

// Testing:
var iPhoneSafari = [
  "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1",
  "Mozilla/5.0 (Apple-iPhone7C2/1202.466; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543 Safari/419.3",
  "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1",
  "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1",
  "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5370a Safari/604.1",
  "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1",
  "Mozilla/5.0 (iPhone9,3; U; CPU iPhone OS 10_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A403 Safari/602.1",
  "Mozilla/5.0 (iPhone9,4; U; CPU iPhone OS 10_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A403 Safari/602.1",
];
console.log("All true:", iPhoneSafari.map(iOSSafari));

var iPhoneNotSafari = [
  "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/69.0.3497.105 Mobile/15E148 Safari/605.1",
  "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/13.2b11866 Mobile/16A366 Safari/605.1.15",
];
console.log("All false:", iPhoneNotSafari.map(iOSSafari));

Merged all the answers and comments.
This is the result.

function iOSSafari(userAgent) {
    return /iP(ad|od|hone)/i.test(userAgent) &&
      /WebKit/i.test(userAgent) &&
      !(/(CriOS|FxiOS|OPiOS|mercury)/i.test(userAgent));
}


// Usage:
// if iOSSafari(window.navigator.userAgent) { /* iOS Safari code here */ }

// Testing:
var iPhoneSafari = [
  "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1",
  "Mozilla/5.0 (Apple-iPhone7C2/1202.466; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543 Safari/419.3",
  "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1",
  "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1",
  "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5370a Safari/604.1",
  "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1",
  "Mozilla/5.0 (iPhone9,3; U; CPU iPhone OS 10_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A403 Safari/602.1",
  "Mozilla/5.0 (iPhone9,4; U; CPU iPhone OS 10_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A403 Safari/602.1",
];
console.log("All true:", iPhoneSafari.map(iOSSafari));

var iPhoneNotSafari = [
  "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/69.0.3497.105 Mobile/15E148 Safari/605.1",
  "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/13.2b11866 Mobile/16A366 Safari/605.1.15",
];
console.log("All false:", iPhoneNotSafari.map(iOSSafari));
梦纸 2024-09-12 03:35:00

掉落的代码只找到mobile safari而没有其他的(除了海豚等小型浏览器)

  (/(iPad|iPhone|iPod)/gi).test(userAgent) &&
  !(/CriOS/).test(userAgent) &&
  !(/FxiOS/).test(userAgent) &&
  !(/OPiOS/).test(userAgent) &&
  !(/mercury/).test(userAgent)

Falling code only find mobile safari and nothing else (except dolphin and other small browsers)

  (/(iPad|iPhone|iPod)/gi).test(userAgent) &&
  !(/CriOS/).test(userAgent) &&
  !(/FxiOS/).test(userAgent) &&
  !(/OPiOS/).test(userAgent) &&
  !(/mercury/).test(userAgent)
残月升风 2024-09-12 03:35:00

看到所有的答案,这里有一些关于建议的正则表达式的提示:

  • AppleWebKit 也匹配桌面 Safari(不仅是移动设备),
  • 不需要多次调用 .match 如此简单正则表达式,并且更喜欢较轻的 .test 方法。
  • g(全局)正则表达式标志是无用的,而i(不区分大小写)可能有用,
  • 无需捕获(括号),我们只是测试

我正在 测试的字符串只是使用这个,因为移动 Chrome 的 true 对我来说是可以的(相同的行为):(

/iPhone|iPad|iPod/i.test(navigator.userAgent)

我只想检测设备是否是 iOS 应用程序的目标)

Seeing all the answers, here are some tips about the proposed RegExes:

  • AppleWebKit matches Desktop Safari too (not only mobile)
  • no need to call .match more than once for such simple regexes, and prefer the lighter .test method.
  • the g (global) regex flag is useless while the i (case insensitive) can be useful
  • no need for capture (parenthesis), we are just testing the string

I'm just using this since getting true for mobile Chrome is OK for me (same behavior):

/iPhone|iPad|iPod/i.test(navigator.userAgent)

(I just want to detect if the device is a target for an iOS app)

江挽川 2024-09-12 03:35:00

这个正则表达式对我有用,干净简单:

const isIOSSafari = !!window.navigator.userAgent.match(/Version\/[\d\.]+.*Safari/);

This regex works for me, clean and simple:

const isIOSSafari = !!window.navigator.userAgent.match(/Version\/[\d\.]+.*Safari/);
你的往事 2024-09-12 03:35:00

事实上,检测移动游猎并没有什么灵丹妙药。有相当多的浏览器可能会使用mobile safari的用户代理的关键字。也许你可以尝试特征检测并不断更新规则。

Actually, there isn't a silver bullet of detecting mobile safari. There are quite a few browsers may use the keywords of the user agent of mobile safari. Maybe you can try feature detection and keep updating the rule.

枯寂 2024-09-12 03:35:00

我知道这是一个旧线程,但我想与大家分享我的解决方案。

我需要检测用户何时从桌面 Safari 导航(因为我们正处于 2017 年中期,Apple 还没有为 input[type="date"] 提供任何支持......所以

,我为它做了一个后备自定义日期选择器)。但仅适用于桌面版 Safari,因为该输入类型在移动版 Safari 中工作正常。因此,我制作了这个正则表达式来仅检测桌面 Safari。我已经测试过它,它与 Opera、Chrome、Firefox 或 Safari Mobile 不匹配。

希望它可以帮助你们中的一些人。

if(userAgent.match(/^(?!.*chrome).(?!.*mobile).(?!.*firefox).(?!.*iPad).(?!.*iPhone).*safari.*$/i)){
  $('input[type="date"]').each(function(){
    $(this).BitmallDatePicker();
  })
}

I know this is an old thread, but I'd like to share my solution with you guys.

I needed to detect when an user navigates from Desktop Safari (Because we're in middle 2017, and Apple hasn't give any support for input[type="date"] YET...

So, I made a fallback custom datepicker for it) . But only applies to safari in desktop because that input type works fine in mobile Safari. So, I made this Regex to only detect desktop Safari. I already tested it and it doesn't match with Opera, Chrome, Firefox or Safari Mobile.

Hope it may help some of you guys.

if(userAgent.match(/^(?!.*chrome).(?!.*mobile).(?!.*firefox).(?!.*iPad).(?!.*iPhone).*safari.*$/i)){
  $('input[type="date"]').each(function(){
    $(this).BitmallDatePicker();
  })
}
单身情人 2024-09-12 03:35:00

我赞成@unwitting 的回答,因为它不可避免地让我继续前进。然而,当在 iOS Webview 中渲染我的 SPA 时,我需要对其进行一些调整。

function is_iOS () {
    /*
        Returns (true/false) whether device agent is iOS Safari
    */
    var ua = navigator.userAgent;
    var iOS = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i);
    var webkitUa = !!ua.match(/WebKit/i);

    return typeof webkitUa !== 'undefined' && iOS && webkitUa && !ua.match(/CriOS/i);
};

主要区别在于,将 webkit 重命名为 webkitUa,以防止与用作消息处理程序之间的根 webkit 对象发生冲突。水疗& UIView.

I upvoted @unwitting 's answer, as it inevitably got me going. However, when rendering my SPA in an iOS Webview, I needed to tweak it a bit.

function is_iOS () {
    /*
        Returns (true/false) whether device agent is iOS Safari
    */
    var ua = navigator.userAgent;
    var iOS = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i);
    var webkitUa = !!ua.match(/WebKit/i);

    return typeof webkitUa !== 'undefined' && iOS && webkitUa && !ua.match(/CriOS/i);
};

The main difference being, the renaming of webkit to webkitUa, so as to prevent clashing with the root webkit object used as a message handler between the SPA & UIView.

有深☉意 2024-09-12 03:35:00

我正在寻找这个答案,我记得我以前遇到过这个。

在 JavaScript 中检测 iOS 上的 Safari 最可靠的方法是

if (window.outerWidth === 0) {
    // Code for Safari on iOS
} 

or 

if (window.outerHeight === 0) {
    // Code for Safari on iOS
} 

出于某种原因,iOS 上的 Safari 为 window.outerHeight 属性和 window.outerWidth 属性返回 0。

这适用于所有 iOS 版本上的所有 iPad 和 iPhone。所有其他浏览器和设备此属性都可以正常工作。

不确定他们是否打算改变这一点,但目前效果良好。

I was looking for this answer and I remembered I came across this before.

The most reliable way to detect Safari on iOS in JavaScript is

if (window.outerWidth === 0) {
    // Code for Safari on iOS
} 

or 

if (window.outerHeight === 0) {
    // Code for Safari on iOS
} 

For some reason Safari on iOS returns 0 for window.outerHeight property and window.outerWidth property.

This is for all iPads and iPhones on all versions of iOS. Every other browser and device this property works normally.

Not sure if they intend to change this but for now it works well.

孤城病女 2024-09-12 03:35:00

基于不知情这里的答案是正则表达式,如果有人需要它。

/^(?=.*(iPhone|iPad|iPod))(?=.*AppleWebKit)(?!.*(criOS|fxiOS|opiOS|chrome|android)).*/i

Based on unwitting answer here is regex if someone needs it.

/^(?=.*(iPhone|iPad|iPod))(?=.*AppleWebKit)(?!.*(criOS|fxiOS|opiOS|chrome|android)).*/i
百善笑为先 2024-09-12 03:35:00

已经很多年了,Apple 仍然没有修复移动 Safari 上的底部固定定位 (100vh) 错误。即使其他所有浏览器都工作正常。

因此,如果 userAgent 是 Webkit Safari,那么对于 Chrome 甚至 Brave 和其他 Webkit 浏览器,还有一个供应商属性会显示“Google, Inc”,除非它显示“Apple Computer Inc”。在这种情况下,它是 Safari。

为了避免 Desktop Safari 中的误报,您还需要 maxTouchPoints 属性,对于移动设备,该属性为 5,对于桌面设备,该属性为 0。可怕,我知道。

const isSafari =
  navigator.userAgent.match(/safari/i) &&
  navigator.vendor.match(/apple/i) &&
  navigator.maxTouchPoints;

if (isSafari) 
  $("body").classList.add("mobile-safari");

然后使用 mobile-safari 类在 CSS 中进行调整。

It's been many years and Apple still hasn't fixed their bottom fixed positioning (100vh) bug on mobile Safari. Even though every other browser works fine.

So, There's also a vender property that'll say "Google, Inc" for Chrome and even Brave, other Webkit browsers if the userAgent is Webkit Safari unless it says "Apple Computer Inc." in which case it's Safari.

To avoid false positives in Desktop Safari, you need the maxTouchPoints property as well, which will be 5 for mobile and 0 for desktop. Horrifying, I know.

const isSafari =
  navigator.userAgent.match(/safari/i) &&
  navigator.vendor.match(/apple/i) &&
  navigator.maxTouchPoints;

if (isSafari) 
  $("body").classList.add("mobile-safari");

Then make adjustments in the CSS using that mobile-safari class.

携余温的黄昏 2024-09-12 03:35:00
function isIOS {
  var ua = window.navigator.userAgent;
  return /(iPad|iPhone|iPod).*WebKit/.test(ua) && !/(CriOS|OPiOS)/.test(ua);
}
function isIOS {
  var ua = window.navigator.userAgent;
  return /(iPad|iPhone|iPod).*WebKit/.test(ua) && !/(CriOS|OPiOS)/.test(ua);
}
如梦初醒的夏天 2024-09-12 03:35:00
var isApple = false;    
if(/iPhone|iPad|iPod/i.test(navigator.userAgent)) {      
  isApple = true;
}
var isApple = false;    
if(/iPhone|iPad|iPod/i.test(navigator.userAgent)) {      
  isApple = true;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文