[Day 1] 前言

與 iOS 開發的相遇 大家好,我是個從律師轉職的軟體工程師,踏入這個領域不知不覺也快兩年了。回想當初轉換跑道,一切從自學 Python 開始,接著摸索資料庫、API 等後端技術。後來有幸進入 AppWorks School (現已更名為 AiWorks) 接受 iOS App 開發訓練,最終進入金融業的 IT 部門。 進入公司後,我的工作日常相當「精彩」,除了本行的 iOS 專案開發與維護,還得兼顧後端維運、和 SQL 打交道,甚至管理 Splunk、Kong APIM 這些系統。雖然實際能投入在 iOS 開發的時間不如預期,但我對這塊領域的熱情從未減少。親手打造出一個能看、能用、能互動的應用程式,那種從無到有的創造感與成就感,是其他工作難以比擬的。也因此,剛進公司時,對於無法專注在 iOS 開發上,心裡難免有些失落。但現在回頭看,我相信廣泛接觸不同技術對一個軟體開發者來說絕對是不虧的事情。然而,心中那份對 iOS、特別是 SwiftUI 的渴望,依然強烈。 目前公司的專案仍以 Objective-C 與 UIKit 為主,雖然我曾用 SwiftUI 開發並上架過個人 App,但總覺得學得不夠扎實。這次鐵人賽,對我來說正是一個完美的機會,能強迫自己更多了解 SwiftUI 的世界,將那些零散的知識串連起來。 初入 DevOps 世界 在公司任職期間,我有幸參與了 Azure DevOps 的導入過程。坦白說,起初它對我而言,就只是個「新來的工具」:用 Wiki 寫文件、開 Work Items 追蹤任務、等 Pipeline 編譯出 .ipa 檔,然後透過 Pull Request (PR) 進行程式碼審查。每個環節都得遵循特定流程,像是 Pipeline 還需要主管審核才能部署,有時覺得有些繁瑣。 但隨著時間推移,這些經驗讓我逐漸體會到,DevOps 不僅僅是工具的堆砌,它更是一種文化,一種讓開發、測試與部署流程更順暢、更可靠的思維模式。當我看到一個小小的修改,能自動觸發測試、打包、甚至部署到測試環境,我才真正理解自動化所帶來的安心感。 即使現在是一人開發的個人專案,我也相信導入良好的 DevOps 實踐也是一個不錯的嘗試: 版本控制: 使用 Azure Repos 搭配 Git-flow 策略,讓每一次的程式碼異動都有所依循。 自動化測試: 設定 Pipeline 自動執行單元測試,確保程式碼品質。 持續整合: 每次提交程式碼後自動編譯並檢查。 持續部署: 自動將測試通過的版本部署到 App Store Connect。 這次的系列文章,我將結合 SwiftUI 開發與 DevOps 實踐,從建立基礎專案開始,一步步實現自動化的開發流程。 ...

September 14, 2025 · 1 分鐘

Azure ReplaceTokens 字串轉義問題

問題現象 在某個專案中,CI/CD 過程需要將設定以 token 替換的方式寫入 JSON 檔案,其中一個欄位包含多行文字內容。在 pipeline 中使用了 qetza.replacetokens.replacetokens-task.replacetokens@5 這個 Azure DevOps Task: - task: qetza.replacetokens.replacetokens-task.replacetokens@5 displayName: 'Replace token in xxx-config.json' inputs: targetFiles: '$(System.ArtifactsDirectory)\\drop\\$(Build.BuildId)\\xxx-config.json' 完成替換並部署到測試環境後,發現無法正常啟動。檢查部署產出的 JSON 檔案時,發現原本應為多行的字串中的 \n,在處理後變成了 \\n。 這導致程式在解析該欄位時,無法還原出原本的格式,進而發生錯誤。 問題原因 查閱文件後發現,ReplaceTokens 預設會對變數值進行 escape 處理。這對一般情況有幫助,但對於需要保留格式的多行字串(如憑證或編碼內容)就會導致格式錯誤。 解法:使用 noescape() 函數停用自動 escape ReplaceTokens 支援開啟轉換函數(Transformations)功能,可用來自訂變數處理方式。具體做法如下: 步驟 1:啟用 enableTransforms 在 ReplaceTokens 的 YAML 設定中加上 enableTransforms: true - task: qetza.replacetokens.replacetokens-task.replacetokens@5 displayName: 'Replace token in xxx-config.json' inputs: targetFiles: '$(System.ArtifactsDirectory)\\drop\\$(Build.BuildId)\\xxx-config.json' enableTransforms: true # 要加這行 步驟 2:修改 JSON,使用 noescape() 將目標檔案中的 token 改寫為: { "config_content": "#{noescape(multiline_config)}#" } 如此可讓 \n 在替換後仍保持原始格式,不會被轉成 \\n。 ...

July 9, 2025 · 1 分鐘

Azure Pipeline 編譯 iOS App Groups 權限未簽入問題

前言 公司原本的上線流程最近要走 Azure DevOps 方式上線,我維護的 iOS App 不外乎也要走這個流程。原本測試都沒有太大問題,但上線之後發現 App Groups 功能沒有正確運作,就開始查找問題,最終找到問題所在並解決,記錄一下過程,並延伸相關知識。 Trouble Shooting 一開始覺得很奇怪,這次上線的內容並沒有異動到 App Group 的設定,所以應該跟 source code 沒有太大關係。後來先嘗試在本機 build 一版,結果發現透過這個方式運作正常,但透過 Azure pipeline build 出來的就會發生問題。因此轉向研究 pipeline yaml 的設定是否出現狀況。 先進一步確認透過 Azure pipeline 包出來的 artifacts 內容是否正確,一般而言,iOS App 打包後的成品如下: DistributionSummary.plist ExportOptions.plist YourAppName.ipa Packaging.log 查看 .ipa 我們可以查看 YourAppName.ipa 裡面到底簽入了哪些權限: 解壓縮 .ipa 檔案: unzip YourAppName.ipa -d AppContents 進入 Payload 目錄: cd AppContents/Payload 執行 codesign 指令: codesign -d --entitlements :- YourAppName.app 每個部分的含義是: codesign:呼叫程式碼簽署工具 d:表示 “display”,用於顯示簽署資訊 -entitlements :-:要求工具顯示應用程式中包含的所有權限(entitlements) 這裡的 :- 是一個特殊的語法,表示將輸出導向到標準輸出(stdout) YourAppName.app:要檢查的應用程式套件路徑 如果有正確簽入 App Groups 的權限,應該要有 <key>com.apple.security.application-groups</key> 的蹤跡,但發現透過 Azure pipeline 包出來 .ipa 沒有。 ...

July 3, 2025 · 2 分鐘