[Day 8] 讀取與解析 CSV 資料

前言 在 App 開發中,有時需要從專案內置的資源檔(如 CSV、JSON)讀取資料。CSV 是用逗點分隔值的檔案,我們可以將之轉化為 SwiftUI 列表。這項操作技能很實用,因為許多資料都是以這種簡單的格式儲存的,而我們這次要實作的 App 也會需要使用到這個功能,因此有必要先了解一下這個主題。 要完成這個任務,我們需要理解並掌握以下幾個核心概念: 讀取 App 內部檔案:學習如何使用 Bundle 來定位並讀取包含在我們 App 安裝包內的資源檔案,例如這次要用的 products.csv。 資料解析 (Parsing):取得原始的文字資料後,我們需要將其一行一行地解析,並將每個欄位轉換成我們定義好的 Product 資料結構,這個過程稱為資料解析。 動態列表 List:這個我們在昨天有使用過了,今天也會用到它。 Identifiable 協定:我們的資料模型(Product struct)必須遵循 Identifiable 協定,告訴 SwiftUI 如何唯一識別每一個項目。 那我們就開始吧。 Step 1:將 products.csv 加入 Xcode 專案 我們先將 products.csv 檔案拖曳到 Xcode 左側的專案導覽器中,並確保在跳出的視窗中勾選了 “Copy files to destination” 以及您的 App Target。 按下 Finish 後,可以看到檔案成功被加入到專案裡頭。 Step 2:定義產品資料模型 我們需要建立一個 struct 來對應 CSV 中的每一行資料。為了讓 SwiftUI 的 List 能識別每個項目,這個 struct 必須遵循 Identifiable 協定。 ...

September 21, 2025 · 4 分鐘

[Day 7] SwiftUI 列表與導航

台 7 線 15k SwiftUI 列表與導航 在 iOS 中,列表(List)和導航(Navigation)是兩個非常重要的基礎元件。前者用於展示大量資料,後者則為畫面切換機制。今天我們將探討這兩個重要的主題,並透過實作一個簡單的列表應用來理解相關概念。 List 元件與 ForEach 的基本使用 SwiftUI 的 List 元件使用方式如下: struct ContentView: View { ![alt text](image.png) var body: some View { List { ForEach(items, id: \.self) { item in Text(item) } } } } 在上面的例子中,我們使用了 ForEach 來遍歷陣列中的元素。 id 是什麼? id 參數用於為 ForEach 中的每個項目提供唯一的標識符。SwiftUI 透過這個標識符來識別和追蹤 list 中的每個視圖。當使用 id: \.self 時,表示直接使用被遍歷集合中的元素本身作為其唯一標識符。這種方式適用於集合中的元素本身是簡單且唯一的類型,例如 Int、String。 使用 \.self 作為 id 的前提是,你的資料集合 items 中的元素類型必須遵守 Hashable 協議。Hashable 能確保每個元素都可以被計算出一個唯一的雜湊值,從而讓 SwiftUI 能區分它們。 ...

September 20, 2025 · 2 分鐘

Linux file descriptor issue

Linux file descriptor issue File descriptor 基本概念 現代作業系統會把記憶體分成兩個區域,分別是 User space(使用者空間)和 Kernel space(核心空間)。使用者的程式會在 User space 執行,系統核心則在 Kernel space 執行。 而使用者的程式沒有權限直接存取硬體資源,但系統核心可以,像是讀寫本機檔案需要存取硬碟、建立 socket 需要用到網卡等等。因此,使用者的程式如果想要讀寫檔案,必須透過 system call 向 Kernel 發出請求。當核心收到使用者程式的 system call 時,會負責存取硬體,並把結果回傳給程式。 承上,File Descriptor 之所以存在,就是因為使用者程式無法直接存取硬體。因此,當程式向核心發出 system call 來開啟一個檔案時,核心會在使用者 process 中分配一個標識該檔案的東西,這個東西就是 FD。 FD 與引用計數 當程式要取用檔案,向 kernal 發起 system call open() 時, kernal 會在 global file table 裡面會為該檔案分配一筆紀錄,並且在 process 的 file descriptor table 中分配一個整數索引,檔案名稱在目錄樹與 inode(實體資料區塊)之間維持引用計數。 而當程式移除檔案 rm filename (即呼叫 unlink())時,kernal 只會將目錄中對該檔案名稱的引用移除,並且將引用計數減一。只要計數仍大於 0,表示至少一個 process 仍然持有該檔案的 FD,inode 與資料區塊就不會被回收。 ...

September 19, 2025 · 1 分鐘

[Day 6] SwiftUI 基礎元件與佈局

SwiftUI 基礎元件介紹 在昨天中,我們學習了 Swift 語言的基礎語法。今天,我們要開始探索 SwiftUI 的基本元件和佈局方式。SwiftUI 採用宣告式語法,讓我們能夠更直覺地描述介面該長什麼樣子,而不是一步步告訴程式要如何建立它。 基本元件介紹 Text:文字顯示 Text 是 SwiftUI 中最基本的文字顯示元件,可以加上各種修飾符來調整外觀: Text("Hello, SwiftUI!") .font(.title) // 設定字型大小 .foregroundColor(.blue) // 設定文字顏色 .bold() // 設定粗體 .padding() // 加上內距 而 padding 本身是透明的,所以這裡是看不出來的。因此我們可以改成這樣: Text("Hello, SwiftUI!") .font(.title) .foregroundColor(.blue) .bold() .background(.yellow) // 加上黃色背景 .padding() .background(.blue) // 加上藍色背景 我們替這個 Text 先加上黃色背景,然後再加上 .padding() 修飾符,最後再加上藍色背景,最後效果如上圖所示。 這裡可以帶出一個 SwiftUI 蠻重要的觀念,蠻值得一提的觀念: SwiftUI 修飾符的順序與「視圖組合」概念 上面 Text 的程式碼可以這樣分析: Text("Hello, SwiftUI!") 最先被 background(.yellow) 包裹,這是「文字本身範圍」的背景。接著 .padding() 為文字 + 黃背景增加內距。最後再套用 .background(.blue),這個藍色背景覆蓋在包含內距的整個區域上。 ...

September 19, 2025 · 3 分鐘

[Day 5] Swift 語言快速入門(二)

流程控制 今天要來講流程控制以及 class, sturct。這些是構成程式邏輯的基礎,理解它們,你就能讓 App 根據不同狀況做出反應。 Swift 提供多種流程控制語法,讓你根據條件或重複執行程式碼。 1. 條件判斷:if / else if / else let score = 85 if score >= 90 { print("太棒了,A級!") } else if score >= 60 { print("及格!繼續努力!") } else { print("不及格!別灰心!") } 你也可以用 && (AND) 和 || (OR) 來組合更複雜的條件: let hasHomework = true let isTired = false if hasHomework && !isTired { // 必須完成作業「而且」不能累 print("趕快寫作業!") } 2. switch 判斷 Swift 的 switch 必須窮盡所有可能性(exhaustive),你不能漏掉任何一種情況,否則編譯器會報錯。這能幫我們避免很多 bug。 default 就是用來處理除了 case 以外所有情況。 let animal = "dog" switch animal { case "cat": print("貓貓") case "dog": print("狗狗") default: print("其他動物") } 3. 迴圈 for-in Swift 的 for-in 迴圈可以用兩種範圍語法: ...

September 18, 2025 · 2 分鐘