[iOS] 「每日一太空」面試題目解析

 前幾天在網路上夢到一個面試題目(總算不是 GitHub Users 了),覺得可以當作一個練習。


 

  1. 第一個頁面只需要有一個 Button 換場到下一個頁面。
  2. 第二個頁面要把 API 的內容呈現,需要呈現的項目有兩個,分別是"title”、"url”,title 是 String,url是圖案的網址,要在 cell 內的 imageView 中呈現,每一橫列放四個格子。
  3. 第三個頁面是點擊了第二個頁面後的任一格,推入下一頁,要呈現當格的背景圖 (hdurl)、date、title、copyright 和 description,date格式為2020 Dec. 17 頁面要能滑動,以看到完整的內容。


注意事項:

  • UI要能自動適應各尺寸大小的螢幕
  • 實作請使用 Swift
  • 禁止使用第三方套件
  • 禁止使用 SwiftUl 框架,請使用 UlKit 框架
  • 除了上述指定 UI 條件之外,你也可以自行優化沒指定的 UI

 

看起來很簡單的需求,卻意外地花時間。

我覺得主要的原因,還是我對 iOS APP 的開發不是很熟練。再加上這次我心血來潮,想用用看網路上被吹上天的 AppCode,為了熟悉新的作業環境又花了一點時間。

接著就來說說這個小專案的實作心得吧。

 

 

因為這個小專案只是一個測驗,規模很小,只要一個故事板(Storyboard)就可以滿足需求了。但是開發的速度要快!這是面試現場就要做給面試官看的;如果是複試前丟的 Coding Test 就還好。

 



第一個畫面就只有這樣,只要確認受試者知道怎麼換頁就好。

 


第二個畫面就比較有戲了,這個部分除了要對接 API,畫面的呈現還要按照需求,呈現 4 個一列的樣子。

 

 

讓畫面呈現 4 個一列的部分,我是參考彼得潘的文章去實作的,要讓畫面在每個設備下都是相同的,不能夠用固定的值,得依照一個公式去計算 Cell 的尺寸。

 

接著就來介紹最精采的 API 串接了。

開始講解前,應該會有些人覺得 API 串接不就是下載網路上的東西,再平凡不過的事是可以難到哪去?我一開始也是這麼想的⋯⋯

 


說到 API 串接,有些有經驗的看倌會想到這個資料物件製作利器 quickType。我一開始也是想說有了這個一切都簡單啦!

 


然後就寫出這一段程式。

 


但就是不知道為什麼,JSONDecoder 會一直丟出 nil ,不知是花生了省魔術,只好在它解析失敗的時候,緊接著重新讀取一次,直到成功為止⋯⋯

 


直到我去搜尋到這篇文章《找出 JSONDecoder 的 decode 錯誤》,才知道原來 quickType 給的範例是精簡的寫法,其實可以用 do catch 去截取 JSONDecoder 錯誤訊息。 

 

Cannot get Data, error message: keyNotFound(CodingKeys(stringValue: "hdurl", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 1", intValue: 1)], debugDescription: "No value associated with key CodingKeys(stringValue: \"hdurl\", intValue: nil) (\"hdurl\").", underlyingError: nil))

 

這時就發現,原來是因為找不到 hdurl 這個參數,導致解析失敗。

 


雖然 API 說明文件上是說,如果傳送 count 參數給後端,就會回傳隨機的圖片。但是在回傳結果中,還是有幾個沒帶圖片的資料。不知道是不是我會錯意?

 

Cannot get Data, error message: dataCorrupted(Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 27", intValue: 27), CodingKeys(stringValue: "media_type", intValue: nil)], debugDescription: "Cannot initialize MediaType from invalid String value video", underlyingError: nil))

 

另外一個坑是無法把接回來的資料排進列舉的錯誤。上面的訊息字面上的意思,是無法將 video 初始化成 MediaType。

 

 

 

回頭看看從 quickType 取回來的資料物件,發現 MediaType 只有 image 這個項目而已,難怪會發生錯誤。因為當初丟給 quickType 的樣本不夠多,所以只能處理很有限的資料種類。

 

API 文件沒有講解得很細,保險起見一律把所有參數改成 String,選擇性修飾子加好加滿。

不過 Swift 嚴格控制 nil (null) 的操作,所以選擇性修飾子的部分還是看情況,避免程式變得太復雜。

 


其實 quickType 也有提供相關的選項,產出比較單純的物件資料,來防止意料之外的錯誤。

 


 

第三個畫面就比較單純了,就是一個蘿蔔一個坑,排好放好就行。

但前提是蘿蔔坑要對!這裡有滑動頁面的需求,所以外面就先放一個 Scroll View,然後再安排一個 Content View 當作載體,接著才在裡面放東西。

 

承上,我自己的做法是Content View 對齊 Content Layout Guide、並和 Frame Layout Guide 等寬。關於這方面的資訊,可參考彼得潘的《scroll view 決定捲動範圍的 Content Layout Guide》。

Content View 不用設定高度,只要最下面的 Label 和 Content View 的底部靠齊、最上面的 Label 和 Content View 的頂部靠齊就好。

 

 

第三頁的程式不用處理非同步程序,沒有什麼騷操作。這邊只有幾項重點

回傳的 URL 不一定是圖片,如果資料類型是短片(Video)的話, URL 是 YouTube 影片的網址,所以這邊我設計成只處理圖片的網址,避免發生錯誤。

 

這裡有一個日期處理的需求,我做在這個頁面專屬的 ViewModel 裡。不難,但是很花時間,不常在 APP 端處理日期時間的受試者,在時間壓力下可能會慌。

 

最後來談談用 AppCode 做專案的情形吧。我在過程中有遇到一個存檔的坑在 Xcode ,在建置時,會儲存所有的檔案。其實 AppCode 也會,但是在 AppCode 中,如果要編輯 Storyboard 的話,還是會跳到 Xcode。如果沒有自己儲存在 Storyboard 上的變動的話,在 AppCode 建置專案,在設備(實機或模擬器)上看到的,仍然是儲存前的樣子。

這一點也是卡到我的點,一開始還以為是 AppCode 有 Bug⋯⋯

 

上面提到的 API 讀取,或許來源是我自己找的,才會有比較多的「眉角」要注意,如果是面試場地有自建後台的話,情況應該會比較單純。

 

以上就是這個測驗題目的解題過程,心有餘力的話,是還可以雕琢這些畫面的,像是添加 Avtivity Indicator、提升讀取效能等等。但前提是可以快速開發、不閃退。

 

對本拙作有興趣的看倌們,敬請移步至 GitHub 頁面觀摩!


留言

這個網誌中的熱門文章

Flutter 動態配置多環境 - Android Gradle 配置

Azure 建立 Windows 虛擬機器