[譯] 不越獄探索 App 的技巧

學習如何構建其餘應用的五種簡單技巧

Medium 的 iOS應用是一個帶僞導航條的原生應用,而 Product Hunt 則是用 React Native 構建的。前端

Medium iOS 應用(左)和 Product Hunt iOS 應用(右)。android

我是怎麼知道的呢?除了我本身編寫代碼或向開發人員詢問之外,我能夠用幾個簡單的測試來肯定 —— 不須要越獄。ios

想知道我怎麼作的?git

背景

在網絡的「早期」時代,很容易瞭解任何網站是如何創建的。經過在瀏覽器中查看源碼,底層代碼能夠暴露給任何人看到、拿去混淆或者重用。隨着網絡的發展和框架的使用,網站變的愈來愈複雜,到如今,這幾乎是不可能作到的。github

使用 Chrome 檢查 Medium 文章的 HTML。web

App 有相同的問題,但更糟。app 會通過編譯,這意味着原代碼已經從人類可閱讀的格式轉換爲計算機友好格式。面試

雖然有工具能夠反編譯 iOS 應用,但它們須要越獄設備,特殊工具和專業編程知識。我將分享一些不須要任何黑客技巧的策略 —— 只要應用安裝在你的設備上就夠了。編程

關鍵的理念

咱們的策略很簡單:將應用推向極限,期待着出情況。若是咱們能看到它們出現的具體問題,就能夠推斷它們如何工做。後端

咱們將嘗試回答如下問題:瀏覽器

  1. 該應用是原生的嗎?若是不是,它是一個 web view?React Native?PhoneGap?Unity?某種 hybrid?
  2. 使用了哪些 UI 元素?是開箱即用的組件仍是一些自定義的東西?如何使用它們來達到預期的效果?

實驗

爲了收集數據,咱們將作五個測試。我將解釋每項測試如何執行,尋找的目標是什麼以及從結果中能夠得出什麼結論。

咱們將測試:

  1. 按鈕觸摸狀態 👆
  2. 交互式導航欄手勢 🔙
  3. VoiceOver 🔊 4.動態類型🔎
  4. 飛行模式 ✈️

實驗 #1:按鈕觸摸狀態 👆

一個按鈕看起來很簡單。你點擊它,而後發生一些事情。可是,並不是全部的按鈕都是相同的。

咱們將測試按鈕交互的邊緣狀況 —— 用戶不只僅是點擊一下按鈕時的行爲。

iOS 開發新人經常對 UIButton(iOS 上的默認按鈕組件)的交互複雜性感到驚訝。在交互中的不一樣節點有九個事件會發生。

  1. touchDown
  2. touchDownRepeat
  3. touchDragInside
  4. touchDragOutside
  5. touchDragEnter
  6. touchDragExit
  7. touchUpInside
  8. touchUpOutside
  9. touchCancel

(在蘋果開發者文檔中瞭解有關 UIControlEvents 的更多信息。)

幾乎全部的按鈕都會在 touchUpInside 上執行一個動做(當用戶在控件邊界內觸摸並鬆手時)。用戶觸摸時,大多數按鈕都會表現出特殊的狀態。

真正的區別因素是按鈕如何處理 touchDragExittouchDragEnter 事件。當用戶觸摸按鈕時,按鈕如何響應,而後不擡起手指,拖動到按鈕以外,而後再拖回來。

在 iOS 模擬器中測試標準按鈕。

標準的 UIButton 有一些常見的行爲:

  1. 拖回按鈕時的「觸摸區域」大於按鈕的邊界。
  2. 在 touchDragEnter 和 touchDragExit 的時候有一個動畫。

可是,自定義的原生按鈕一般會丟掉這些默認動畫。

沒有動畫的自定義按鈕。

一個例子

咱們來看看 Medium 應用。若是你在 Medium 的 iOS 應用中閱讀此內容,你能夠直接在上面試試!

讓咱們試一下右下角的這個看起來很花哨的按鈕:

若是你點擊按鈕,而後按住不動,將手指向外移動並返回,你會發現手形圖標在其明暗狀態之間切換。

(個人下一篇文章:「我如何經過增加黑客來獲得 10 萬用戶」 😉)

React Native 按鈕

React Native 按鈕很容易認出來。它們一般有一個緩慢的淡入淡出動畫,而且適用於一切 React Native 按鈕。

Facebook 的 F8 應用中的按鈕動畫。這是 React Native 應用程序中的常見效果。

React Native 應用程序一般會大量使用滾動視圖,這會使按鈕的行爲難以測試,由於拖動按鈕也會滾動視圖。

當談到 React Native 的話題時,另外一個泄露祕密的表現就是 cell 的點擊狀態。iOS 的原生 cell 點擊後會出現一個純色背景,而 React Native 的 cell 點擊後與其按鈕相似的高光效果。

左:React Native cell 行爲。右:原生 cell 行爲。

Web View 按鈕

在我下載測試的 PhoneGap 應用程序中,約 95% 的按鈕徹底沒有觸摸狀態,其他的約 5% 保留了觸摸按鈕的狀態,但在拖出或返回時沒有任何表現。

按鈕觸摸狀態的結論

請記住很重要的一點,這些按鈕行爲很容易被重寫。表現出特定的行爲並不意味着一個絕對的緣由 —— 它只是某個方向的線索。

可是隨着時間的推移,你會不自覺對按鈕有一種「感受」,但它是探索 app 如何構建的,作出有根據猜想的最簡單方法之一。(這種技術也能夠用來肯定一個交互元素是一個按鈕仍是其餘類型的控件。)

實驗 #2:交互式導航手勢

從 iOS 7 開始,用戶能夠經過滑動顯示屏的左側邊緣來導航到前一個界面。這個手勢特別有趣,由於它是交互式的,這意味着它能夠搓來搓去。

在 iOS 上使用標準的 UINavigationController 時,這種行爲是自帶的。出於某種緣由,許多應用程序棄用了標準導航欄,並最終致使了導航轉換效果的丟失,損壞或質量不高

讓咱們在 Medium 中試一下。

比較 Medium(左側)和 App Store(右側)上的導航轉換效果。

與標準導航轉換不一樣,Medium app 將導航欄與屏幕的其他部分一塊兒移動。而標準狀況下,導航欄保持不變,上面的全部標籤會淡入淡出。

另外,Medium app 的前一個界面上的黑色半透明疊加層較暗,看起來導航轉換部分被重寫了,或者更有多是直接使用了自定義的組件。

我我的認爲它看起來很是好,而且理解他們出於設計和開發的須要而採起了這種方法。

React Native 導航

從開發的角度來看,React Native 中的導航功能實現起來更加困難。所以,React Native 應用程序傾向於使用自定義導航轉換,而不是使用UINavigationController的標準「push」和「pop」。

Facebook 的 F8 應用程序中的自定義轉換效果。

iOS 上的默認模態演示不是交互式的,而且在從新出現的界面上沒有縮放效果。

如下是 React Native 中自定義轉換的另外一個示例。

Facebook 的 F8 應用中的導航轉換效果。

沒有陰影或黑色疊加,但真正泄露祕密的表現是動畫時機。在這個 gif 中很難看到,可是在我擡手以後,動畫完成比日常慢得多。

就像按鈕觸摸狀態同樣,經過測試許多導航轉換,你能夠在一段時間的後得到一種「感受」。

交互式導航手勢的結論

這是我最喜歡的測試之一,由於它能夠揭示更多關於 app 的信息,而不只僅是導航欄的工做方式。若是手勢把 app 搞出了 bug,則可能獲得的信息不只僅是導航轉換的方式了。

可是,就像按鈕觸摸狀態同樣,導航轉換能夠被重寫。然而實際上,因爲導航轉換須要大量的開發工做,因此導航轉換不太可能被嚴格定製。

實驗 #3:VoiceOver(旁白)🔊

你想要超能力?試試 VoiceOver。

VoiceOver 是 Apple 版本的屏幕閱讀器。適用於視力障礙用戶,這種輔助功能選項會大聲朗讀用戶界面。

VoiceOver 有另外一個咱們更感興趣的效果:它在當前選定的元素周圍顯示一個黑框。

在 App Store 和 Weather 應用程序中選擇元素的聲音。

這使咱們可以將界面分解成各個部分。不須要猜想界面是如何構建的,咱們可讓 VoiceOver 告訴咱們!有時它甚至會大聲朗讀元素的類型(「按鈕」,「日期選擇器」等)。

若是您之前沒有使用過 VoiceOver,那麼它很值得去學習。基本概念:

  1. 在屏幕上拖動以選擇元素。
  2. 雙擊屏幕上的任意位置以「點擊」所選元素。
  3. 左右滑動以在元素之間快速跳轉。

讓咱們來研究一下在 Medium 中使用 VoiceOver 的效果。

使用 VoiceOver 在 Medium 中選擇帖子的標題。

大多數元素的表現和預期一致。VoiceOver 只是讀取選擇的內容或元素的名稱。可是,有一些不尋常的行爲。

在主屏幕上,選擇帖子的標題只能讀取標題的一半。首先它說,「Color Contrast Crash C」,而後選擇標題的底部讀取「Course for Interface Design」。這說明 label 的佈局確定有一些自定義的部分,這使得 VoiceOver 認爲標題被分紅多個 label,每行一個 label。(個人猜想是他們爲自定義行間距的 label 構建了一個變通方案,而一般的解決方案是使用 attributedString 屬性,而且他們的方案可能會致使之後出現複雜問題。)

選擇描述 label 後,咱們能夠看到 VoiceOver 揭示隱藏信息的威力。對於大多數用戶來講,label 只是顯示「估計有 2.85 億...」。可是VoiceOver告訴咱們更多的信息:「估計有 2.85 億人視力受損。這個數字包括從法律上來看這些人的人數「。在這種狀況下說明,全部數據都存儲在標籤中,但視覺上被截斷了。

Medium 的 VoiceOver 演示。(確保你的聲音不是靜音)

若是幸運的話,你可使用它來訪問你沒法訪問的信息。

這是另外一個有趣實驗。在「書籤」選項卡上,若是你沒有書籤,則有一個不可見的標籤。它說:「要給文章加書籤,在任一地方點擊書籤圖標,文章會被添加到這個列表。」

使用 VoiceOver 在 Medium 中選擇不可見標籤。

我猜是開發人員會快速暫時隱藏這個標籤,並假定可能未來產品又會讓它顯示。(或者,也許我正在被 A/B 測試。)

非原生應用程序

VoiceOver 也適用於基於網絡視圖的 app。若是你聽到「連接」或「標題級別」等字眼時,表示你正在一個網絡視圖之中。

此外,文本元素可能會基於樣式以各類奇怪的方式拆分(由於它的 HTML 表示),而且元素可能不會天然分組。

遊戲(由 Unity,SpriteKit 等構建)一般根本沒有任何 VoiceOver 支持。

VoiceOver 的結論

VoiceOver 提供的證據在這些測試中最可靠。它顯示元素的可視範圍,並能夠讀取不可見的屬性。這是關於任何界面的寶貴資料。

隨着你更多地使用 VoiceOver,你會學習到各類 UI 元素的默認表達方式,並開始注意到它的不一樣之處。

與上述任何測試同樣,VoiceOver 不是 100% 可靠的。全部的 VoiceOver 文本和邊界框均可以由開發人員配置。針對 VoiceOver 優化過的應用程序也可能會揭露更少關於應用程序如何工做的信息,由於開發人員會修復可能致使 app 出問題的 bug。

(專業提示:將 VoiceOver 設置爲你的「輔助功能快捷鍵」,便於在測試時打開和關閉。)

實驗 #4:動態類型🔎

與 VoiceOver 相似,動態類型 是適用於視力障礙用戶的輔助功能。它能夠修改整個系統的文字大小。

咱們想要使用動態類型來破壞佈局。有了新的「輔助功能中的更大字體」後,這比以往更容易看出 app 端倪,這絕對是巨大字體。

調至最大字體的「更大文本」設置界面。

動態類型 能夠在設置 > 輔助功能 > 更大字體中設置。這也能夠做爲一個 widget 添加到 iOS 11 中的控制中心,以便於訪問。

不幸的是,Medium 不支持 動態類型,因此咱們將使用 App Store 演示。

我將文字大小設置爲最大值,並找到了一個錯誤的佈局 —— 搜索界面上的一個廣告。

最大字體(左側)和默認字體(右側)的 App Store 搜索界面。

文本「22K」佈局的很是好,但它沒有揭露太多佈局的祕密,由於佈局爲更大字體作了調整(能夠看到元素改位堆疊排列,而不是並排)。

我最喜歡的部分是淡藍色的「廣告」按鈕。和正常字體大小時的漂亮的圓角矩形不一樣,咱們獲得了一個怪怪的拉伸的形狀。

更大字體設置下的「廣告」按鈕。

個人猜想是,這個藍色框被繪製成一個硬編碼半徑的自定義路徑。一般,控件不會使用動態類型調整大小(請參閱「GET」按鈕做爲示例),因此這裏有一些自定義內容。

####動態類型的結論

有些應用程序根本不支持 動態類型。即便支持,他們也可能不支持輔助設置中更大的字體。

可是當動態類型生效時,就能夠對佈局進行壓力測試。使用 VoiceOver 已經能夠了解一些信息,結合動態類型更有助於驗證理論。一般支持動態類型的 app 也會測試這一部分,這會減小顯示有用信息的機會。

實驗 #5:飛行模式✈️

另外一個簡單的測試是啓用飛行模式。飛行模式會禁用 Wi-Fi 和蜂窩移動網絡,這會當即致使網絡請求失敗。經過在各類狀況下禁用網絡鏈接,咱們能夠看到 app 如何出問題。

在 Medium 中,若是你加載主頁,打開飛行模式,並選擇一篇文章,文章仍會加載。事實上,整個帖子仍然可讀。

飛行模式下的 Medium。文字內容加載,但圖像不加載。

由此,咱們推斷 Medium 在加載預覽時會拉取整個帖子的內容(並進行一些緩存)。

App Store 也會延遲加載圖像。加載完一個頁面並滾動到底部以後打開飛行模式會看到圖像區域是空白的。

App Store 在飛行模式下。圖像(即便在同一頁面上)彷佛是懶加載。

大多數現代應用程序重度依賴於網絡鏈接,來下載內容而後容許交互,因此飛行模式會讓大多數 app 出錯。

React Native 和非原生應用

在我測試過的 React Native app 中,大多數應用程序經過刪除屏幕上的全部內容,並顯示一條自定義的「無鏈接」消息,對缺少互聯網鏈接的狀況當即作出反應。

對於基於 webview 的 app,大多數沒有反應。沒有跡象代表當前正在加載或者加載失敗。

飛行模式的結論

不幸的是,飛行模式並無給出如何構建應用程序的明確答案,由於大多數應用程序在沒有可用鏈接時會有某種回退方式。

想繼續深刻?經過觀察 app 的網絡流量,你能夠了解更多關於其餘應用的信息。Charles Proxy(代理)的 iOS app 是洞悉各類 app 的好方法,但須要一些 HTTP 網絡知識。

小貼士

儘管可能不能徹底肯定 app 的構建方式,但有一些方法可讓你進行有根據的猜想。經過研究邊緣案例,咱們能夠更大程度上揭示它們的內部運做。

咱們的學習也能夠爲咱們本身的 app 的設計和開發提供信息。多瞭解一些方法有助於咱們在將來作出更好的決策。

在一個不開源的應用程序的世界中,作些小改動的能力有限。(或從新發現)思考事物運轉的方式的樂趣。


喜歡這個故事?在 Medium 上留言,並與 iOS 設計/開發者朋友分享。想要了解最新的移動應用設計/開發?在 Twitter上關注我:twitter.com/nathangitte…

感謝 David Okun 修改本文的草稿。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索