初學 iOS,老師要求串接鳳凰新聞 API 做 App,拿到 API 文件卻無從下手。
Base URL、端點、參數、回傳結構、認證方式(API Key/OAuth)。URLSession (原生,iOS 7+):dataTask(with:completionHandler:)。Codable (Swift 4+) 定義模型結構體,JSONDecoder 一行解碼。DispatchQueue.main.async { self.tableView.reloadData() }。// Model
struct NewsItem: Codable {
let title: String
let summary: String
let imageUrl: String
let publishTime: Date
let link: String
}
struct ApiResponse: Codable {
let code: Int
let data: [NewsItem]
let message: String
}
// Service
class NewsService {
static let shared = NewsService()
private let baseURL = "https://api.ifeng.com" // 範例,請替換真實文件
private let session = URLSession.shared
func fetchLatest(completion: @escaping (Result<[NewsItem], Error>) -> Void) {
guard let url = URL(string: "\(baseURL)/news/latest") else { return }
var request = URLRequest(url: url)
request.setValue("YOUR_API_KEY", forHTTPHeaderField: "Authorization") // 若需
session.dataTask(with: request) { data, resp, err in
if let err = err { completion(.failure(err)); return }
guard let data = data else { completion(.failure(NSError())); return }
do {
let res = try JSONDecoder().decode(ApiResponse.self, from: data)
completion(.success(res.data))
} catch { completion(.failure(error)) }
}.resume()
}
}
// ViewController
class NewsViewController: UITableViewController {
var items: [NewsItem] = []
override func viewDidLoad() {
super.viewDidLoad()
NewsService.shared.fetchLatest { [weak self] result in
DispatchQueue.main.async {
switch result {
case .success(let list): self?.items = list; self?.tableView.reloadData()
case .failure(let e): print("錯誤:\(e)")
}
}
}
}
override func tableView(_ tv: UITableView, numberOfRowsInSection s: Int) -> Int { items.count }
override func tableView(_ tv: UITableView, cellForRowAt ip: IndexPath) -> UITableViewCell {
let cell = tv.dequeueReusableCell(withIdentifier: "Cell", for: ip)
cell.textLabel?.text = items[ip.row].title
return cell
}
}
| 問題 | 解決 |
|---|---|
| HTTP 載入被阻擋 (ATS) | Info.plist 加 NSAppTransportSecurity → NSAllowsArbitraryLoads = YES (僅開發),生產需 HTTPS。 |
| JSON 欄位名不符 | 用 CodingKeys 映射:enum CodingKeys: String, CodingKey { case imageUrl = "img_url" }。 |
| 日期格式非標準 | let decoder = JSONDecoder(); decoder.dateDecodingStrategy = .formatted(formatter)。 |
| 圖片載入慢/閃爍 | 用 Kingfisher / SDWebImage 非同步快取載入。 |