Try   HackMD
tags: Front-End Safari

【學習筆記】關於 iOS 的那些坑之二:Web API、Resize 與消失的 Console

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Photo by Pandhuya Niking on Unsplash

前言:iOS 之坑、再次襲來

既上篇的「【學習筆記】 關於 iOS Safari 的那些坑:禁止選取 & 縮放設定」之後,因為 Web APP 開發需同時支援 Android 和 iOS 裝置,在過程中仍不時被新的隕石砸中,只好再挖新的坑來填補。

這次要探討的主題比較瑣碎,大致如下:

  • Wait!! Do you know where’s my console?
  • Resize fires multiple times
  • Web API: Fullscreen & Vibration

Wait!! Do you know where’s my console?

儘管仍可查看元件樣式,但主控台呈現一片空白:

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

白天不懂夜的黑,Console 不懂我的悲QQ

How to resolve?

以下提供幾種解決方案:

  • 最土法煉鋼的方法:透過 console.log 大法直接印到 webview 上,但若需要動態更新頁面,例如多國語系功能(i18n),則需要抓取 DOM 的 innerHTML 一個一個置換更新,但非常麻煩且耗費效能
  • 或建立一個 div 容器在頁面上,把需要的 Debug 資訊放在這裡,像是監聽事件等,這做法同樣是透過更新 DOM 元素
  • 或更新 mac 上的 Safari 版本至 16.4,但需注意 Safari 16.4 僅支援 macOS Big Sur 和 macOS Monterey 較新的 macOS 版本,目前手上的 mac 因為版本較舊還沒嘗試此解法

Resize fires multiple times

How to resolve?

這時可透過設定 setTimeout,避免短時間內重複觸發 resize event,範例如下:

let resizeTimer;
window.addEventListener("resize", (e) => {
  if (resizeTimer) clearTimeout(resizeTimer);  // 判斷是否已發生 resize
  resizeTimer = setTimeout(() => {
    // Do something...
  }, 100);
}, false);

Web API: Fullscreen & Vibration

接著要探討的,是 Web API 提供的全螢幕顯示(Fullscreen)以及控制裝置震動(Vibration)功能。不論是在使用什麼 API 之前,都應該先查詢是否支援所需裝置,否則即使實作完成,到最後才發現原來不支援,反而要花更多時間去找別種工具,因此事前評估尤其重要。

Fullscreen API 顯示全螢幕

以下是不同裝置上的瀏覽器對 Fullscreen API 支援度:

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

可以看到 Safari 雖然在行動裝置僅支援到 iOS 12,在 PC 上還是能支援到 16.4。但需注意的是,不像其他瀏覽器,Fullscreen API 只能套用在 video 元素上,若用在其他像是 div 元素時一概沒有反應,這點真的很不友善。

但如果因為功能需求,必須套用在 div 元素上的話,還是有方法可以繞過這個限制,例如透過 PWA 來實現全螢幕效果,外觀就像 Native app 一樣。

What is PWA?

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Ref: https://www.evertop.pl/en/progressive-web-app-pwa/

以下是 MDN 關於 PWA 的介紹:

Progressive Web Apps (PWAs) are web apps that use service workersmanifests, and other web-platform features in combination with progressive enhancement to give users an experience on par with native apps.

漸進式網路應用程式(PWAs)透過 service workersmanifests 技術,並以漸進增強策略,建立跨平台 web 應用程式,提供用戶體驗近似於原生程式的功能。

這裡簡單介紹上述提到的 Service Worker 與 Manifest 兩項技術:

  • Service Worker:可想像是位於 Web App 與網路連接之間的代理人,讓網頁擁夠像 Native App 一樣支援離線和訊息推播功能
  • Manifest:透過設定 manifest.json 檔,可自訂啟動畫面、安裝在主畫面顯示的名稱與 icon 等

透過 PWA 建立跨平台 Web 應用程式,使用者只需將網頁加到主畫面,開啟時就不會顯示網址列,外表就和 Native APP 一樣是全螢幕,能夠有更好的沉浸式體驗。

除此之外,使用 PWA 還有其他好處,像是安裝快速、定義快取、離線瀏覽、可被搜尋等優點,藉此提升使用者體驗。詳細可參考這篇文章:PWA 實戰經驗分享 - Huli's blog,有提到如何實作 PWA 以及不同平台可能遇到的問題的等等。

Vibration API 使裝置震動

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Safari 沒有懸念不支援 Vibration API,但令人感到意外的是 Firefox 也僅支援較低版本。

此外,需注意在 Safari 瀏覽器下呼叫 vibrate() 時,有可能因出現 error 導致無法進行後續動作,最保險的做法還是加上防呆驗證,確定裝置有支援才執行功能。

const userAgent = window.navigator.userAgent;
if(!userAgent.includes('iOS') && !userAgent.includes('Mac OS')) navigator.vibrate();

小記

接續上篇筆記,陸續來回在 Safari 和 Android 裝置進行測試,發現一旦接受「只要遇上 Safari 大多支援度不高」這個事實以後,開發起來就快樂多了,畢竟這也不是工程師煩惱就有用的問題;反而要煩惱不同瀏覽器之間對事件觸發、Web API 支援程度的差異性。

簡言之,該如何從現有的技術去實作近似於目標的功能,先熟悉擁有哪些工具再去談可行性,才是更需要學習的地方。