#37 隨機圖片API &進階版 UIPickerVier
繼上一回的作業練習了串接文字API及UIPickerView基礎練習;
這次練習串接圖片API,共有兩種方式:
1. 用一般 coding 顯示API圖片
2. 用第三方套件 kingfisher 顯示API圖片
另外,也包含了進階題UIPickerView:
1. 點選畫面後顯示 Picker View
2. Picker View 的上方加入包含完成 & 取消 button 的 bar,按下完成時更新畫面的內容
3. 顯示多欄的 Picker View,第二欄的 picker view 隨著第一欄而變化
其他功能
等待畫面時,顯示 UIActivityIndicatorView
等待畫面時,顯示預設圖片
APP畫面:
UIPikerView
基礎版UIPickerView可以參考上一篇:
這裡說明進階版不同的部分:
點選畫面後,UIPickerView才會出現,並搭配著按鈕去取消與選取
新增UIToolbar在畫面外(放在exit底下),並拉好 IBOutlet;
UIPickerView 也是一樣的方式先新增跟拉好
再新增一個TextField放在View裡,在 func viewDidLoad() 裡利用程式碼
optionTextField.inputView = optionPickerView
optionTextField.inputAccessoryView = optionToolBar
讓UIPickerView跟UIToolbar取代觸發時會跳出的鍵盤
用 .becomeFirstResponder( ) 去觸發 TextField
optionTextField.becomeFirstResponder()
這裡是用點兩下畫面觸發顯示UIPickerView跟UIToolbar,所以寫在 UITapGestureRecognizer 的 function 裡
func tapToSelect() {
let tap = UITapGestureRecognizer()
tap.numberOfTapsRequired = 2
tap.addTarget(self, action: #selector(showPickerVier))
pictureImageView.isUserInteractionEnabled = true
pictureImageView.addGestureRecognizer(tap)
}
@objc func showPickerVier() {
optionTextField.becomeFirstResponder()
optionTextField.isHidden = true
}
關於 UITapGestureRecognizer 也可以參考上一篇
仔細觀察,Toolbar 中間其實有三個 item
中間的item,Fixed Space Bar Button Item 是固定兩個item之間的距離
記得 Cancel Button 跟 Get Image Button 也要拉 IBAction,去定義按下時要做的事。例如:收鍵盤
view.endEditing(true)
UIPickerView 裡的資料設定
第一個欄位(component = 0)選取的資料不會出現在第二個欄位(component = 1),也就是不會選到一樣的選項
撰寫程式的概念是:
在 ViewController 裡宣告兩組 array,其中一組包含所有資料,另一組是空 array,搭配移除 array 資料( .remove(at: ) ),與存入資料去改變第二組欄位
if component == 0 {
secondOptions = firstOptions
let firstSelected = pickerView.selectedRow(inComponent: 0)
secondOptions.remove(at: firstSelected)
pickerView.selectRow(2, inComponent: 1, animated: true)
pickerView.reloadComponent(1)
} else if component == 1 {
pickerView.reloadComponent(1)
}
特別注意,因為第二組欄位會因第一組欄位而改變,所以也必須被 reload,不然第二組欄位選取的資料會不正確。
串接API,顯示選取PickerView後的畫面
試了兩種方式串接API來顯示圖片
✨ 使用一般coding
✨ 使用第三方套件(kingfisher)
APP GIF呈現比較:
使用起來幾乎一樣,但用一般 coding 撰寫程式的可以一直按 GetImage 去取得同樣條件下不同的圖片;但用kingfisher的,在同樣條件下,會一直呈現同樣的照片,仔細翻閱文件可以發現原因
它抓過的資料都會暫存起來,讓程式更有效率
一般coding的串接API程式碼:
func fetchImage() {
processIndicator.startAnimating()
optionTextField.isHidden = true
pictureImageView.image = UIImage(systemName: "sailboat")
if let randomURL = URL(string: "https://loremflickr.com/350/400/\(firstOption),\(secondOption)/all") {
print(randomURL.description)
URLSession.shared.dataTask(with: randomURL) { data, response, error in
if let data {
let image = UIImage(data: data)
DispatchQueue.main.async {
self.pictureImageView.image = image
self.pictureImageView.contentMode = .scaleAspectFill
self.processIndicator.stopAnimating()
}
}
}.resume()
}
}
用kingfisher串接API的程式碼:
func fetchImage() {
optionTextField.isHidden = true
if let randomURL = URL(string: "https://loremflickr.com/350/400/\(firstOption),\(secondOption)/all") {
print(randomURL.description)
//顯示未知進度
pictureImageView.kf.indicatorType = .activity
//等待載入影像時,顯示placeholder設定的圖示
let processorRoundCorner = RoundCornerImageProcessor(cornerRadius: 15)
//在影像上覆蓋一層自訂顏色的透明色調
let processorOverLay = OverlayImageProcessor(overlay: .systemOrange)
pictureImageView.kf.setImage(
with: randomURL,
placeholder: UIImage(systemName: "sailboat"),
options: [
.processor(processorRoundCorner),
.processor(processorOverLay)
])
}
}
kingfisher的文件寫得非常清楚,還搭配範例,很適合初學者練習第三方程式與閱讀其文件。
UIActivityIndicatorView
有時網路比較慢或是在載入較大檔案時會花上幾秒時間,可以顯示 UIActivityIndicatorView 去讓使用者知道現在APP的狀態。
關鍵的三行程式碼:
開始運作:
processIndicator.startAnimating()
停止運作:
processIndicator.stopAnimating()
停止運作時自動隱藏:
processIndicator.hidesWhenStopped = true
GitHub:
一般coding
使用第三方套件kingfisher