iT邦幫忙

2025 iThome 鐵人賽

DAY 24
0
Mobile Development

Swift iOS 開發新手村:從入門到 AI 聊天室系列 第 24

Day 24|Xcode 滾動選取:PickerView & NASA 實戰應用(第一天)

  • 分享至 

  • xImage
  •  

昨天我們學會了如何像「建築師」一樣規劃 MVC 架構,讓專案變得井然有序。今天,我們就要立刻學以致用,親手搭建一個結構清晰、功能酷炫的 App!

這次的主題,讓我們望向星空——我們將串接 NASA 的「每日天文一圖」API!你將學會如何使用滾筒式的 選取器(PickerView),讓使用者能輕鬆地選擇日期,並即時從 NASA 伺服器抓取回傳的太空美照。這將是我們第一個結合了 專業架構UI 元件真實網路資料 的實戰專案!

今日學習重點

  • 認識並解析 API:了解如何申請 NASA API Key,並使用線上工具解析回傳的 JSON 格式。
  • 打造資料模型:學習使用 Codable 將 JSON 結構對應到 Swift 的 struct
  • 設計 App 畫面:在 Xib 中規劃 ImageView, PickerView, Button 的基本佈局。
  • 封裝網路邏輯:撰寫一個可重複使用的 NetworkManager,並處理各種潛在的網路錯誤。

一、解析 NASA API JSON

首先,前往 NASA Open APIs 申請 API Key。

填寫基本資料後,就會在信箱收到 API Key:
https://ithelp.ithome.com.tw/upload/images/20251008/20177542DGLaKuOCOG.png
接著往下滑,選擇 APOD: Astronomy Picture of the Day
https://ithelp.ithome.com.tw/upload/images/20251008/20177542Ln3MzDzsh0.png
點擊 Example query 範例連結,複製 JSON 回傳的內容:
https://ithelp.ithome.com.tw/upload/images/20251008/20177542fz5SQOizMg.png
打開 Json Parser Online,將 JSON 貼上:
https://ithelp.ithome.com.tw/upload/images/20251008/201775429cZk8eebtK.png
對照右側結構,在 Xcode 中新增 apiNASA.swift,建立資料結構:

struct apiNASA: Codable {
    
    var date: String
    
    var explanation: String
    
    var hdurl: String
    
    var media_type: String
    
    var service_version: String
    
    var title: String
    
    var url: String
}

使用 Codable 可以自動解析 JSON,並方便與 NetworkManager 搭配。

二、設計 App 介面

今天我們先在 .xib 設計主要畫面,包含三個元件:

  • UIImageView:顯示 NASA 天文圖片
  • UIPickerView:讓使用者選擇日期(年/月/日三欄)
  • UIButton:確認選擇日期後抓取圖片

建議介面佈局:

------------------------
|      UIImageView     |
------------------------
|     UIPickerView     |
------------------------
|       UIButton       |
------------------------

記得拉好 Auto Layout 約束,避免元件在不同裝置跑版。

三、撰寫 NetworkManager

將網路請求集中管理,方便 MainViewController 直接呼叫:

import Foundation

class NetworkManager {
    
    // 建立 singleton,方便整個專案使用
    static let shared = NetworkManager()
    
    // 私有建構子,避免外部再建立新的實例
    private init() {}
    
    // 封裝抓取 NASA APOD 資料的函式
    func fetchNASAData(for date: String? = nil, completion: @escaping (Result<apiNASA, Error>) -> Void) {
        // 1️⃣ API URL
        // 記得將 "貼上你的API_KEY" 改成你申請的 Key
        var urlString = "https://api.nasa.gov/planetary/apod?api_key=貼上你的API_KEY"
        if let date = date {
            // 如果有傳入日期,就加上 &date=yyyy-MM-dd
            urlString += "&date=\(date)"
        }
        
        // 2️⃣ 將字串轉成 URL
        guard let url = URL(string: urlString) else {
            // 如果字串無法轉成 URL,直接回傳錯誤
            completion(.failure(NSError(domain:"Invalid URL", code:0)))
            return
        }
        
        // 3️⃣ 發送網路請求
        URLSession.shared.dataTask(with: url) { data, response, error in
            // 3a. 如果請求出現錯誤
            if let error = error {
                completion(.failure(error))
                return
            }
            
            // 3b. 檢查 HTTP 狀態碼是否成功
            if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 200 {
                completion(.failure(NSError(domain: "HTTP Error", code: httpResponse.statusCode)))
                return
            }
            
            // 3c. 確認有回傳資料
            guard let data = data else {
                completion(.failure(NSError(domain:"No data", code:0)))
                return
            }
            
            // 4️⃣ 將 JSON 解析成 Swift 結構
            do {
                let decoder = JSONDecoder()
                let result = try decoder.decode(apiNASA.self, from: data)
                // 成功解析後,透過 completion 回傳資料
                completion(.success(result))
            } catch {
                // 如果解析失敗,回傳錯誤
                completion(.failure(error))
            }
        // 5️⃣ 啟動請求
        }.resume()
    }
}

說明

  1. Singleton(單例)
    • static let shared = NetworkManager()
    • 這樣整個 App 只會有一個 NetworkManager 實例,方便全域使用。
  2. URLSession.dataTask
    • 這是 iOS 提供的非同步網路請求方法。
    • 會在背景線程抓取資料,不會阻塞畫面。
  3. completion handler
    • @escaping (Result<apiNASA, Error>) -> Void
    • 意思是「網路抓到資料或發生錯誤後,會回傳結果給呼叫者」,這樣 MainViewController 就能拿到資料更新畫面。
  4. JSONDecoder
    • 將回傳的 JSON 轉成 Swift 物件(我們的 apiNASA 結構)。
    • Codable 讓解析非常簡單,不需要手動抓每個欄位。
  5. 非同步 UI 更新
    • URLSessioncompletion handler 是在背景線程執行的。因此,明天當我們在 MainViewController 中拿到 NetworkManager 回傳的資料後,任何更新畫面的操作(如設定 UIImageView 的圖片)都必須被放到主線程 DispatchQueue.main.async 中執行,否則 App 可能會閃退或畫面無反應。

小結一下

今天,我們扮演了 NASA App 的「首席工程師」,完成了所有看不見但至關重要的幕後工程!

我們從一份來自 NASA 的藍圖(JSON)開始,學會了如何用 Codable 將它打造成堅固的資料模型。更厲害的是,你還親手建立了一個專業、可重複使用的網路引擎(NetworkManager),它不僅採用了 Singleton 模式,還具備了完整的錯誤處理機制。

這個強大的網路層,是你從「單機 App」邁向「連網 App」的關鍵基石。「萬事俱備,只欠東風」——明天,我們就要把這陣東風(UI 互動)吹起來,讓一切完美運作!

🌟 明日預告

明天,我們將回到 MainViewController,扮演總指揮的角色。你將學會如何實作 UIPickerViewdataSourcedelegate,讓它能顯示年、月、日的滾動選項。

最精彩的部分是,當使用者按下按鈕後,我們將會呼叫 NetworkManager 去抓取 NASA 的資料,並學會在背景執行緒安全地更新 UI,將美麗的太空圖片顯示在畫面上。這將是將所有零件組合成一個完整產品的關鍵一課!

敬請期待《Day 25|Xcode 滾動選取:PickerView & NASA 實戰應用(第二天)》


上一篇
Day 23|Xcode 架構教學:掌握 MVC 設計模式
系列文
Swift iOS 開發新手村:從入門到 AI 聊天室24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言