List — คืออะไร, คอมโพเนนต์รายการใน SwiftUI

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-06-25 เวลาอ่าน: 7 นาที

List คือ View คอนเทนเนอร์ใน SwiftUI สำหรับแสดงข้อมูลเป็นรายการที่เลื่อนในแนวตั้งได้ คล้ายกับ UITableView ใน UIKit ตาม Apple Developer Documentation, 2024 List รองรับส่วนแบบคงที่และไดนามิก การปัดเพื่อดำเนินการ การเรียงลำดับแถวใหม่ และการดึงเพื่อรีเฟรช แตกต่างจาก UITableView ตรงที่ List ใช้ API เชิงประกาศที่อิงตาม SwiftUI และ ForEach จัดการการนำเซลล์กลับมาใช้ใหม่และประสิทธิภาพโดยอัตโนมัติเมื่อมีแถวจำนวนมาก

ประเด็นสำคัญ

  • List — คอนเทนเนอร์สำหรับรายการข้อมูลที่เลื่อนได้ใน SwiftUI
  • ForEach — วิธีหลักในการแสดงข้อมูลแบบไดนามิกใน List
  • ส่วน — Section View สำหรับจัดกลุ่มแถวด้วยหัวเรื่อง
  • การปัดเพื่อดำเนินการ — swipeActions สำหรับ iOS 15+
  • การดึงเพื่อรีเฟรช — .refreshable สำหรับ iOS 15+

List ใน SwiftUI คืออะไร?

List คือ View ที่แสดงลำดับของรายการในรายการที่เลื่อนในแนวตั้งได้ มันถูกนำมาใช้ใน iOS 13 พร้อมกับ SwiftUI และเป็นวิธีหลักในการแสดงรายการข้อมูล แทนที่ UITableView จาก UIKit List จัดการการนำเซลล์กลับมาใช้ใหม่ การเลื่อน และประสิทธิภาพโดยอัตโนมัติ

List ใช้การโหลดแบบขี้เกียจ: เซลล์จะถูกสร้างขึ้นเมื่อคุณเลื่อน ไม่ใช่ทั้งหมดในครั้งเดียว ซึ่งแตกต่างจาก VStack กับ ForEach ภายใน ScrollView ที่เซลล์ทั้งหมดถูกสร้างขึ้นในขณะเรนเดอร์ List ยังรองรับการปัดเพื่อดำเนินการ การดึงเพื่อรีเฟรช การแก้ไข (ลบ/ย้าย) และการเลือกแถวในตัว

ตาม Apple WWDC 2021 (Session 10072) List ใน iOS 15+ ได้รับการปรับปรุงประสิทธิภาพอย่างมีนัยสำคัญด้วยกลไกการเปรียบเทียบความแตกต่างใหม่ในระดับคอลเลกชัน ซึ่งทำให้ List มีประสิทธิภาพมากขึ้นเมื่ออัปเดตข้อมูล โดยเฉพาะสำหรับรายการที่มีแถวนับร้อย

List เทียบกับ ScrollView + VStack

นักพัฒนามักเลือกระหว่าง List และ ScrollView กับ VStack เพื่อแสดงชุดของ Views ความแตกต่างหลัก: List ใช้การนำเซลล์กลับมาใช้ใหม่ (เช่น UITableView) ในขณะที่ ScrollView + VStack สร้าง Views ทั้งหมดทันที สำหรับรายการขนาดคงที่ (สูงสุด 20 รายการ) ความแตกต่างนั้นเล็กน้อย สำหรับรายการไดนามิกที่มี 50+ แถว List เหมาะสมกว่าในแง่ประสิทธิภาพ

รายการแบบคงที่และไดนามิก

รายการแบบคงที่ คือรายการที่มีจำนวนแถวคงที่ซึ่งระบุโดยตรงในเนื้อหาของ List ใช้สำหรับเมนู การตั้งค่า และฟอร์มที่มีชุดรายการที่ทราบ แต่ละแถวถูกประกาศอย่างชัดเจน โดยไม่มีลูปหรือ ForEach

swift
// รายการแบบคงที่ (สำหรับเมนูและการตั้งค่า)
List {
    Text("โปรไฟล์")
    Text("การตั้งค่า")
    Text("เกี่ยวกับ")
}

// รายการแบบไดนามิก (สำหรับข้อมูล)
struct UserList: View {
    let users: [User]

    var body: some View {
        List(users) { user in
            HStack {
                Text(user.name)
                Text(user.role)
                    .foregroundColor(.secondary)
            }
        }
    }
}

รายการแบบไดนามิก ใช้ตัวเริ่มต้น List(data:rowContent:) หรือ ForEach ภายในเนื้อหาของ List วิธีแรกสะดวกเมื่อแต่ละแถวสอดคล้องกับหนึ่งรายการข้อมูล วิธีที่สองมีประโยชน์เมื่อมีส่วนหรือรายการเพิ่มเติมระหว่างข้อมูล

การระบุ (Identifiable): สำหรับรายการไดนามิก รายการข้อมูลต้องเป็นไปตามโปรโตคอล Identifiable หรือคุณต้องระบุ KeyPath ไปยังตัวระบุที่ไม่ซ้ำกันใน tuple data:id SwiftUI ใช้ตัวระบุเพื่อติดตามการเปลี่ยนแปลง: การเพิ่ม การลบ และการย้ายแถว

ส่วนและการจัดกลุ่มข้อมูล

Section คือ View สำหรับจัดกลุ่มแถวใน List ด้วยหัวเรื่องและส่วนท้ายที่เป็นตัวเลือก Section ยอมรับ header และ footer เป็น ViewBuilder ทำให้สามารถใช้ไม่เพียงแค่ข้อความ แต่ยังใช้ Views แบบกำหนดเองสำหรับหัวเรื่องส่วนได้

swift
struct SettingsView: View {
    var body: some View {
        List {
            Section(header: Text("บัญชี")) {
                Text("ชื่อ")
                Text("อีเมล")
            }
            Section(header: Text("การแจ้งเตือน")) {
                Toggle("Push", isOn: $pushEnabled)
                Toggle("Email", isOn: $emailEnabled)
            }
        }
        .listStyle(.insetGrouped)
    }
}

// ส่วนไดนามิกด้วย ForEach
List {
    ForEach(groupedData.keys.sorted(), id: \.self) { key in
        Section(header: Text(key)) {
            ForEach(groupedData[key]!) { item in
                Text(item.title)
            }
        }
    }
}

สไตล์ของ List: SwiftUI มีสไตล์ในตัวหลายแบบผ่านตัวปรับแต่ง .listStyle() .insetGrouped — มาตรฐานสำหรับ iOS Settings, .plain — มินิมอล, .inset — มีการเยื้อง, .sidebar — สำหรับ Sidebar บน iPad

ตาม SwiftUI Cookbook (2024) Section ที่มีส่วนไดนามิกและ ForEvaluate ภายในเป็นรูปแบบมาตรฐานสำหรับการจัดกลุ่มข้อมูลในแอปพลิเคชันที่มีโครงสร้างซับซ้อน กฎสำคัญ: อย่าวาง Section ซ้อนภายใน Section และอย่าใช้ตัวเริ่มต้น List(data:) ร่วมกับ Section — ให้ใช้ ForEach ภายในเนื้อหาของ List

การปัดเพื่อดำเนินการและการดึงเพื่อรีเฟรช

.swipeActions(edge:allowsFullSwipe:content:) — ตัวปรับแต่งสำหรับ iOS 15+ ที่เพิ่มการปัดเพื่อดำเนินการให้กับแถวของ List ช่วยให้แสดงปุ่มเมื่อปัดไปทางซ้าย (ค่าเริ่มต้น) หรือขวา พร้อมสีและบทบาทที่แตกต่างกัน (destructive, cancel)

swift
struct TaskList: View {
    @Binding var tasks: [Task]

    var body: some View {
        List {
            ForEach($tasks) { $task in
                Text(task.title)
                    .swipeActions(edge: .trailing) {
                        Button("ลบ", role: .destructive) {
                            tasks.removeAll { $0.id == task.id }
                        }
                    }
                    .swipeActions(edge: .leading) {
                        Button(task.isDone ? "เลิกทำ" : "เสร็จสิ้น") {
                            task.isDone.toggle()
                        }
                        .tint(.green)
                    }
            }
        }
        .refreshable {
            // การโหลดข้อมูลแบบอะซิงโครนัส
            await loadTasks()
        }
    }
}

.refreshable — ตัวปรับแต่งสำหรับ iOS 15+ ที่เพิ่มการดึงเพื่อรีเฟรช ยอมรับคลosureแบบอะซิงโครนัสที่จะทำงานเมื่อผู้ใช้ดึงรายการลงมา SwiftUI จะแสดงตัวบ่งชี้การโหลดโดยอัตโนมัติ หลังจากการดำเนินการเสร็จสิ้น ตัวบ่งชี้จะถูกซ่อน

.onDelete และ .onMove — ตัวปรับแต่งสำหรับ iOS 13+ ที่เพิ่มการรองรับการลบและการเรียงลำดับแถวใหม่ ในการใช้งาน ให้ห่อข้อมูลใน ForEach ด้วย Binding หรือส่งคลosureผ่าน .onDelete(perform:) บน List หรือ ForEach

ประสิทธิภาพของ List และการปรับให้เหมาะสม

ประสิทธิภาพของ List ขึ้นอยู่กับจำนวนแถว ความซับซ้อนของแต่ละเซลล์ และความถี่ในการอัปเดตข้อมูล SwiftUI ใช้การโหลดแบบขี้เกียจและการนำเซลล์กลับมาใช้ใหม่ (คล้ายกับ UITableView.dequeueReusableCell) แต่อาจจำเป็นต้องปรับให้เหมาะสมเพิ่มเติมสำหรับรายการที่มี 500+ แถว

การปรับให้เหมาะสมคำอธิบายเวอร์ชัน iOS
IdentifiableID ที่ไม่ซ้ำกันสำหรับแต่ละรายการiOS 13+
EquatableViewหลีกเลี่ยงการวาดใหม่เมื่อข้อมูลเท่ากันiOS 13+
id(_:)บังคับสร้าง View ใหม่เมื่อ ID เปลี่ยนแปลงiOS 13+
.equatable()การเปรียบเทียบอย่างเคร่งครัดตาม EquatableiOS 15+
Diffable dataการเปรียบเทียบความแตกต่างอัตโนมัติเมื่อมีการเปลี่ยนแปลงiOS 15+

ปัญหา 1: การอัปเดตบ่อยครั้ง หากข้อมูลในรายการได้รับการอัปเดตบ่อยครั้ง (เช่น ทุกวินาที) List อาจวาดเซลล์ที่มองเห็นใหม่ทุกครั้งที่สถานะเปลี่ยนแปลง วิธีแก้ไข: ใช้โครงสร้าง (value types) สำหรับข้อมูล — SwiftUI เปรียบเทียบตามค่าและวาดเฉพาะแถวที่เปลี่ยนแปลงใหม่

ปัญหา 2: เซลล์ที่มีน้ำหนักมาก หากแต่ละแถวมีลำดับชั้น View ที่ซับซ้อน รูปภาพ และแอนิเมชัน การเลื่อนอาจช้าลง วิธีแก้ไข: แยกเซลล์ออกเป็น Views แยกต่างหาก ใช้ EquatableView เพื่อป้องกันการวาดใหม่ที่ไม่จำเป็น ตาม SwiftUI Lab (2024) การแบ่งแถวที่ซับซ้อนออกเป็นส่วนประกอบย่อยช่วยลดเวลาในการเรนเดอร์ลง 30–50%

ปัญหา 3: จำนวนแถวมาก ด้วย 1000+ แถว List ยังคงทำงานได้อย่างมีประสิทธิภาพด้วยการโหลดแบบขี้เกียจ แต่การโหลดเริ่มต้นอาจช้าลงเนื่องจากการคำนวณเค้าโครง วิธีแก้ไข: ใช้ LazyVStack เฉพาะสำหรับรายการที่มีแถวเหมือนกันซึ่งไม่จำเป็นต้องใช้คุณสมบัติของ List (การปัด ส่วน) สำหรับรายการที่มีคุณสมบัติครบถ้วน List ยังคงเป็นตัวเลือกที่ดีที่สุด

คำถามที่พบบ่อย

List ใน SwiftUI คืออะไร?

List คือ View คอนเทนเนอร์สำหรับแสดงรายการข้อมูลที่เลื่อนได้ใน SwiftUI เทียบเท่ากับ UITableView ใน UIKit พร้อม API เชิงประกาศ รองรับส่วน การปัดเพื่อดำเนินการ การดึงเพื่อรีเฟรช การแก้ไข และการปรับแต่งผ่าน .listStyle()

List แตกต่างจาก ScrollView + VStack อย่างไร?

List ใช้ การโหลดแบบขี้เกียจและการนำเซลล์กลับมาใช้ใหม่ — เซลล์จะถูกสร้างขึ้นเมื่อคุณเลื่อน ScrollView + VStack สร้าง Views ทั้งหมดในครั้งเดียว สำหรับรายการที่มี 50+ แถว List เหมาะสมกว่า สำหรับชุดขนาดเล็กคงที่ (สูงสุด 20 รายการ) ความแตกต่างนั้นเล็กน้อย

จะเพิ่มการดึงเพื่อรีเฟรชให้กับ List ได้อย่างไร?

ใช้ตัวปรับแต่ง .refreshable (iOS 15+) ส่งคลosureแบบอะซิงโครนัสพร้อมตรรกะการอัปเดตข้อมูล SwiftUI จะแสดงตัวบ่งชี้การโหลดโดยอัตโนมัติและซ่อนหลังจากดำเนินการแบบอะซิงโครนัสเสร็จสิ้น

จะจัดกลุ่มแถวใน List ได้อย่างไร?

ใช้ Section View พร้อมหัวเรื่องและส่วนท้ายที่เป็นตัวเลือก วางแถวรายการภายใน Section สำหรับส่วนไดนามิก ให้ใช้ ForEach กับ groupedData สไตล์รายการถูกกำหนดค่าผ่าน .listStyle(.insetGrouped) เพื่อให้มีลักษณะคล้าย iOS

จะทำให้ List มีแถวจำนวนมากเร็วขึ้นได้อย่างไร?

ใช้ โครงสร้าง (value types) สำหรับข้อมูล แยกเซลล์ที่ซับซ้อนออกเป็น Views แยกต่างหากด้วย EquatableView หลีกเลี่ยงการอัปเดตสถานะบ่อยครั้งในแต่ละแถว สำหรับรายการที่มี 1000+ แถว ให้พิจารณา LazyVStack หากไม่จำเป็นต้องใช้คุณสมบัติของ List

สรุป

  • List — คอนเทนเนอร์สำหรับรายการที่เลื่อนได้พร้อมการโหลดแบบขี้เกียจและการนำเซลล์กลับมาใช้ใหม่
  • ForEach — วิธีหลักในการแสดงข้อมูลแบบไดนามิกใน List
  • Section — การจัดกลุ่มแถวด้วยหัวเรื่องและส่วนท้าย
  • swipeActions — การปัดเพื่อดำเนินการสำหรับ iOS 15+
  • refreshable — การดึงเพื่อรีเฟรชสำหรับ iOS 15+
  • สไตล์ — insetGrouped, plain, inset, sidebar ผ่าน .listStyle()
  • ประสิทธิภาพ — ใช้ Identifiable, EquatableView และ value types

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม