คู่มือบทช่วยสอน

ดึงอัตราแลกเปลี่ยนใน Swift ด้วย URLSession

ใช้ URLSession, Codable และ URLComponents พร้อมเก็บข้อมูลเวลาที่อัปเดต เพื่อแสดงอัตราแลกเปลี่ยนในแอป Swift บน iOS และ macOS

8 ก.ย. 2569 · อ่าน 6 นาที

ให้ URLSession จัดการเครือข่ายและ Codable จัดการ JSON คีย์จริงควรอยู่ที่ server ไม่ใช่ในแอป iOS, macOS หรือ watchOS.

  • กำหนด response model: เก็บ rates, source, market_session และ data_updated_at ใน model และใช้ Decimal กับจำนวนเงิน.
  • เก็บคีย์ไว้ที่ server: แอปมือถือเรียก backend ของคุณ แล้ว backend เติม Authorization ส่วน Swift ฝั่ง server อ่านคีย์จาก environment ได้.
  • จัดการสถานะและ freshness: ตรวจสอบ HTTP status ก่อน decode แยก 401 กับ 429 และแสดงเวลาและ source ให้ผู้ใช้เห็น.

กำหนด response model

เก็บ rates, source, market_session และ data_updated_at ใน model และใช้ Decimal กับจำนวนเงิน.

swift · ExchangeRateClient.swift
import Foundationfinal class NoRedirects: NSObject, URLSessionTaskDelegate {    func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) {        completionHandler(nil)    }}struct Latest: Decodable {    let base: String    let source: String    let marketSession: String    let dataUpdatedAt: String    let rates: [String: Decimal]}struct ExchangeRateClient {    let session: URLSession    let apiKey: String?    func latest(base: String) async throws -> Latest {        let normalizedBase = base.uppercased()        guard normalizedBase.count == 3, normalizedBase.allSatisfy({ $0.isASCII && $0.isLetter }) else {            throw URLError(.badURL)        }        guard var components = URLComponents(string: "https://api.exchangerate.dev/v1/latest/\(normalizedBase)") else {            throw URLError(.badURL)        }        components.queryItems = [URLQueryItem(name: "symbols", value: "EUR,GBP,JPY")]        guard let url = components.url else { throw URLError(.badURL) }        var request = URLRequest(url: url)        request.timeoutInterval = 10        if let apiKey { request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") }        let (data, response) = try await session.data(for: request)        guard let http = response as? HTTPURLResponse, (200..<300).contains(http.statusCode) else {            throw URLError(.badServerResponse)        }        let decoder = JSONDecoder()        decoder.keyDecodingStrategy = .convertFromSnakeCase        return try decoder.decode(Latest.self, from: data)    }}

เก็บคีย์ไว้ที่ server

แอปมือถือเรียก backend ของคุณ แล้ว backend เติม Authorization ส่วน Swift ฝั่ง server อ่านคีย์จาก environment ได้.

swift · server setup
let key = ProcessInfo.processInfo.environment["EXCHANGERATE_API_KEY"]let session = URLSession(configuration: .ephemeral, delegate: NoRedirects(), delegateQueue: nil)let client = ExchangeRateClient(    session: session,    apiKey: key)let latest = try await client.latest(base: "USD")print(latest.rates["EUR"] as Any, latest.source, latest.dataUpdatedAt)

จัดการสถานะและ freshness

ตรวจสอบ HTTP status ก่อน decode แยก 401 กับ 429 และแสดงเวลาและ source ให้ผู้ใช้เห็น.

เก็บบริบทของอัตราไว้ด้วย

รายงานรายวันใช้วันละครั้ง ส่วน dashboard อาจใช้ทุกชั่วโมง เมื่อเจอ 429 ให้ลดความถี่ ไม่ใช่สร้าง retry ทันที.

  • เก็บอัตราพร้อม source และเวลา.
  • ใช้กับ automation และการวิเคราะห์.
  • อย่าใช้เป็นราคาที่ execute ได้.

คำถาม

ใส่คีย์ใน iOS ได้ไหม?

ไม่ได้ เพราะดึงออกจาก app bundle ได้ ให้เก็บไว้ที่ server.

ไม่ใช้คีย์ได้ไหม?

ได้ ภายใต้ข้อจำกัดการทดลองแบบ anonymous.

ทำไมใช้ Decimal?

เพื่อหลีกเลี่ยงความคลาดเคลื่อนของ floating point.

ทำอย่างไรหลังได้ 429?

ลดความถี่ ไม่ retry ทันที และทำตามขีดจำกัดของแผน.

อ่านต่อ

เริ่มต้นด้วยคีย์ API ฟรี

ส่งคำขอได้ 5,000 ครั้งต่อเดือนด้วยแพ็กเกจฟรี ไม่ต้องใช้บัตรเครดิต

รับคีย์ฟรี