嗨,大家今天過得好嗎?歡迎來到鐵人賽 Day 11。
過去 10 天,我們在前端 SwiftUI 的泥淖裡打滾,成功把殼跟架構都捏出來了。現在前端已經準備好一份精美的「預算與需求」資料,正等著發送出去。
今天,我們要正式喚醒在 Day 3 用 Docker 架設好的 n8n 引擎。我們要在 n8n 裡建立一個「接收端」,也就是所謂的 Webhook,並把 iOS App 裡的假資料 (Mock Data) 替換成真正的網路請求,徹底打通前後端的任督二脈!
請打開瀏覽器,進入你的 n8n 本地端後台(預設是 http://localhost:5678)。
Webhook 並點擊新增。POST(因為前端要傳遞 JSON 資料過來)。recommend(這是我們自訂的 API 路由,網址最後會長得像 /webhook-test/recommend)。When Last Node Finishes(這非常重要!這代表 n8n 會等後續所有邏輯、包含 AI 產出結果後,才把資料回傳給前端,否則它會立刻回傳一個空白的 OK)。設定好之後,把節點視窗關起來。你會看到畫布上的 Webhook 節點上方有一個 「Test URL」。點擊它並複製這個網址(應該會是 http://localhost:5678/webhook-test/recommend)。
小知識:Test URL vs Production URL
n8n 的 Webhook 有分兩種。開發階段我們都用Test URL,要點擊畫面下方的「Execute Workflow」它才會開始監聽;等專案正式上線、啟用 (Active) 後,才會換成常駐監聽的Production URL。
後端入口準備好了,現在我們要把目光切回 Xcode。
還記得我們在 Day 8 寫的那個用 Task.sleep 假裝讀取的 APIService.swift 嗎?現在我們要用 Vibe Coding 把它換成真正的 URLSession 網路請求。
打開 Prompt 視窗,下這段指令:
請幫我修改 SwiftUI 專案中的 `APIService.swift`。
1. 將原本的 Mock Data 邏輯移除。
2. 改用 `URLSession` 發送真實的 POST 請求。
3. 目標 URL 為:`http://localhost:5678/webhook-test/recommend`
4. 請將 `budget` (Int) 與 `purpose` (String) 打包成 JSON 作為 HTTP Body 發送。
5. 預期回傳的資料依然可以解析為原本的 `HardwareMenu` Model。
請給我完整修改後的 APIService.swift 程式碼,並處理好 Error Handling。
AI 應該會吐給你一段非常標準的 Swift 網路請求程式碼,大概長這樣:
import Foundation
class APIService {
static let shared = APIService()
private init() {}
func fetchRecommendation(budget: Int, purpose: String) async throws -> HardwareMenu {
guard let url = URL(string: "http://localhost:5678/webhook-test/recommend") else {
throw URLError(.badURL)
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let payload: [String: Any] = ["budget": budget, "purpose": purpose]
request.httpBody = try JSONSerialization.data(withJSONObject: payload)
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
throw URLError(.badServerResponse)
}
return try JSONDecoder().decode(HardwareMenu.self, from: data)
}
}
這時候如果你滿心歡喜地按下 Xcode 的執行 (Run),然後點擊 App 裡的「產生推薦菜單」...
恭喜你,App 絕對會噴錯!
你會在 Xcode 下方的 Console 看到類似這樣的錯誤訊息:The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.
這也是新手 Vibe Coding 常踩的雷。AI 幫你寫了完美的網路連線程式碼,但它不會主動告訴你:蘋果 (Apple) 預設是禁止 App 發送不安全的 HTTP 請求的。 因為我們 n8n 是架設在本地端的 http://localhost,沒有 SSL 憑證 (HTTPS),所以直接被 iOS 系統給擋下來了。
解法非常簡單,只要修改專案設定檔:
Info.plist (如果是純 SwiftUI 專案,請點擊專案藍色 Icon ➔ Targets ➔ Info 頁籤)。App Transport Security Settings。Allow Arbitrary Loads,並把值設為 YES。這樣就成功解除 iOS 對我們本地開發伺服器的封印了!
太棒了!今天我們跨出了全端開發最重要的一步,成功讓 SwiftUI 與 n8n 搭上了線。
不過,如果剛剛你的 App 轉圈圈轉到一半當掉是正常的,因為我們的 n8n 目前只接收了資料,還沒有把 HardwareMenu 的格式回傳給前端,導致前端解析 JSON 失敗。
明天,我們要在 n8n 工作流裡面進行「資料變形」,並實作一組真正的 Response,把資料塞回去給我們的前端!
我們 Day 12 見!