View Protocol — แนวคิดหลัก, โปรโตคอล View ใน SwiftUI

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

View Protocol เป็นโปรโตคอลพื้นฐานของ SwiftUI ที่ส่วนประกอบอินเทอร์เฟซที่มองเห็นได้ทุกตัวต้องปฏิบัติตาม ตาม Apple Developer Documentation, 2024 View กำหนดสัญญาเดียว: โครงสร้างหรือคลาสที่ใช้โปรโตคอลนี้ต้องระบุคุณสมบัติที่คำนวณได้ body ผ่านโปรโตคอลนี้ SwiftUI สร้างลำดับชั้นหน้าจอทั้งหมดตั้งแต่ป้ายข้อความธรรมดาไปจนถึงโครงสร้างการนำทางที่ซับซ้อน

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

  • View Protocol — โปรโตคอลพื้นฐานของ SwiftUI ที่องค์ประกอบที่มองเห็นทั้งหมดปฏิบัติตาม
  • body — ข้อกำหนดบังคับเพียงอย่างเดียวของโปรโตคอล ที่ส่งคืนเนื้อหา
  • some View — ชนิดทึบแสงที่ซ่อนชนิดรูปธรรมของ View ที่ส่งคืน
  • @ViewBuilder — result builder ที่รวบรวมหลาย Views เป็นองค์ประกอบเดียว
  • View — เป็นชนิดค่า (struct) ซึ่งรับประกันการอัปเดตอินเทอร์เฟซที่คาดเดาได้

View Protocol ใน SwiftUI คืออะไร?

View Protocol เป็นโปรโตคอลหลักของ SwiftUI ที่กำหนดว่าองค์ประกอบที่มองเห็นได้ใดๆ อธิบายเนื้อหาของตนอย่างไร แตกต่างจาก UIKit ที่แต่ละองค์ประกอบสืบทอดจาก UIView ผ่านคลาส SwiftUI ใช้แนวทางเชิงโปรโตคอล: ชนิดใดก็ตามที่ปฏิบัติตามโปรโตคอล View สามารถแสดงบนหน้าจอได้

โปรโตคอล View ต้องการการใช้งานคุณสมบัติที่คำนวณได้เพียงอย่างเดียว body ที่ส่งคืนเนื้อหาบางส่วน อย่างไรก็ตาม เบื้องหลังความเรียบง่ายนี้มีระบบองค์ประกอบที่ทรงพลัง: body สามารถส่งคืนชนิดใดก็ได้ที่ปฏิบัติตาม View รวมถึงชนิดพื้นฐาน (Text, Image, Button) ตัวเก็บ (VStack, HStack, ZStack) และส่วนประกอบประกอบแบบกำหนดเอง

ตาม WWDC 2023 มากกว่า 95% ของหน้าจอทั้งหมดในแอปพลิเคชัน SwiftUI ถูกสร้างขึ้นผ่านองค์ประกอบของโครงสร้างที่ใช้โปรโตคอล View ทำให้ View Protocol เป็นรากฐานของสถาปัตยกรรม SwiftUI ทั้งหมด

ชนิดค่าเทียบกับชนิดอ้างอิง

SwiftUI กำหนดให้ View เป็น ชนิดค่า (value type) (struct) ไม่ใช่คลาส นี่คือการตัดสินใจทางสถาปัตยกรรมที่สำคัญ: ชนิดค่ามีอายุการใช้งานที่คาดเดาได้ ไม่มีสถานะที่เปลี่ยนแปลงได้ร่วมกัน และช่วยให้ SwiftUI สามารถระบุได้อย่างมีประสิทธิภาพว่าส่วนใดของลำดับชั้นเปลี่ยนแปลงและต้องการการวาดใหม่

หากคุณพยายามทำให้ View เป็นคลาส คอมไพเลอร์จะแสดงข้อผิดพลาด: โปรโตคอล View สืบทอดจากโปรโตคอล DynamicViewProperty ซึ่งต้องการความหมายของค่า (value semantics) คลาสสามารถปฏิบัติตาม View ได้ แต่สิ่งนี้ทำลายแนวทางตามสำนวนและสูญเสียประโยชน์ของการอัปเดตอัตโนมัติ

body: คุณสมบัติที่คำนวณได้ของโปรโตคอล View

body เป็นข้อกำหนดบังคับเพียงอย่างเดียวของโปรโตคอล View เป็นคุณสมบัติที่คำนวณได้ซึ่งส่งคืนเนื้อหาที่แสดงบนหน้าจอ ชนิดที่ส่งคืนคือ some View ซึ่งหมายถึง “ชนิดที่ปฏิบัติตาม View ซึ่งจะถูกกำหนดโดยคอมไพเลอร์”

swift
struct GreetingView: View {
    var name: String

    var body: some View {
        VStack {
            Text("Hello, \(name)!")
                .font(.title)
                .foregroundColor(.blue)
            Button("Start") {
                print("Button pressed")
            }
        }
    }
}

body ทำงานอย่างไร: SwiftUI เรียก body ทุกครั้งที่สถานะของแอปพลิเคชันเปลี่ยนแปลงและจำเป็นต้องวาดใหม่ เฟรมเวิร์กเปรียบเทียบทรี View ใหม่กับทรีเก่าและใช้เฉพาะการเปลี่ยนแปลงที่จำเป็น (diffing) นี่เป็นแนวทางเชิงประกาศอย่างสมบูรณ์ — คุณอธิบายสิ่งที่ควรแสดง และ SwiftUI จัดการวิธีการนำไปใช้

รายละเอียดสำคัญ: body ต้องไม่มีผลข้างเคียง มันถูกเรียกหลายครั้งตลอดอายุของแอปพลิเคชัน และหาก body เปลี่ยนแปลงสถานะภายนอก — สิ่งนี้นำไปสู่พฤติกรรมที่คาดเดาไม่ได้ สำหรับผลข้างเคียง ให้ใช้ task, onChange หรือ DispatchQueue

ข้อจำกัดจำนวนองค์ประกอบ

SwiftUI กำหนดข้อจำกัด: body สามารถส่งคืนองค์ประกอบรากได้เพียงตัวเดียวเท่านั้น หากคุณต้องการแสดงหลายองค์ประกอบในระดับเดียวกัน ให้ห่อไว้ในตัวเก็บ — VStack, HStack, ZStack หรือ Group เมื่อมีการนำ @ViewBuilder มาใช้ ข้อจำกัดนี้สังเกตเห็นได้น้อยลง แต่ในเชิงแนวคิด body จะส่งคืน View เดียวเสมอ

some View: ชนิดทึบแสงในโปรโตคอล

some View เป็นไวยากรณ์ชนิดทึบแสง (opaque type) ที่นำมาใช้ใน Swift 5.1 โดยเฉพาะสำหรับ SwiftUI หมายความว่าฟังก์ชันหรือคุณสมบัติส่งคืนชนิดรูปธรรมที่ปฏิบัติตามโปรโตคอล View แต่โค้ดที่เรียกไม่ทราบและไม่จำเป็นต้องทราบว่าชนิดใดที่แน่นอนถูกส่งคืน

คอมไพเลอร์ Swift กำหนดชนิดรูปธรรมในเวลาคอมไพล์สำหรับแต่ละการใช้งาน body แต่ซ่อนไว้จากโลกภายนอก สิ่งนี้ช่วยให้ SwiftUI ปรับลำดับชั้น View ให้เหมาะสมโดยรู้ชนิดที่แน่นอนของส่วนประกอบทั้งหมด ขณะเดียวกันให้ความยืดหยุ่นแก่นักพัฒนาในการเปลี่ยนการใช้งานโดยไม่ต้องเปลี่ยนลายเซ็น

swift
struct ContentView: View {
    var body: some View {
        Text("Hello, World!") // Compiler knows this is Text
    }
}

ทำไม some View และไม่ใช่แค่ View? ถ้า body ส่งคืนเพียง View (เป็นโปรโตคอล) SwiftUI จะไม่สามารถระบุชนิดรูปธรรมในเวลาคอมไพล์ได้ สิ่งนี้เพิ่มค่าใช้จ่ายในการห่อในคอนเทนเนอร์เชิงوجود (existential container) some View ให้ข้อมูลเพียงพอแก่คอมไพเลอร์สำหรับการปรับแต่ง ในขณะที่รักษาความยืดหยุ่นของโปรโตคอล

ข้อจำกัดของ some View

ข้อจำกัดหลักคือ body ต้องส่งคืนชนิดเดียวกัน คุณไม่สามารถส่งคืน Text ในสาขาหนึ่งของเงื่อนไขและ Image ในอีกสาขาหนึ่งได้โดยไม่มีตัวห่อพิเศษ (AnyView, Group หรือ @ViewBuilder) คอมไพเลอร์ตรวจสอบสิ่งนี้ในเวลาคอมไพล์: เส้นทางส่งคืนที่เป็นไปได้ทั้งหมดต้องมีชนิดเดียวกัน

เพื่อหลีกเลี่ยงข้อจำกัดนี้ ให้ใช้ @ViewBuilder (สร้างชนิด TupleView เดียว), Group (ซึ่งส่งคืนชนิดเดียว) หรือ AnyView (ลบชนิดแต่เพิ่มค่าใช้จ่าย) AnyView ควรใช้เมื่อตัวเลือกอื่นเป็นไปไม่ได้เท่านั้น เนื่องจากมันปิดการปรับแต่งของ SwiftUI

@ViewBuilder: การประกอบหลาย Views

@ViewBuilder เป็น result builder ที่คำอธิบายประกอบอนุญาตให้รวบรวมหลาย Views เป็นองค์ประกอบเดียวโดยไม่ต้องมีตัวเก็บที่ซ้อนกัน @ViewBuilder จะห่อหลายนิพจน์ใน tuple (TupleView) โดยอัตโนมัติ หรือใช้ตรรกะตามเงื่อนไข (If / else / switch) ด้วยชนิดส่งคืนที่ถูกต้อง

swift
struct DashboardView: View {
    var isLoggedIn: Bool

    @ViewBuilder
    var body: some View {
        if isLoggedIn {
            Text("Welcome!")
                .font(.largeTitle)
            ProfileCard()
        } else {
            LoginButton()
                .padding()
        }
    }
}

@ViewBuilder ทำงานอย่างไร: คอมไพเลอร์แปลงแต่ละบล็อกโค้ดภายใน @ViewBuilder เป็นการเรียกเมธอดสแตติก buildBlock, buildEither, buildOptional ฯลฯ ถ้าบล็อกมีหลายนิพจน์ — พวกมันจะถูกห่อใน TupleView ถ้าบล็อกมีตรรกะตามเงื่อนไข — คอมไพเลอร์สร้าง ConditionalContent โดยซ่อนชนิดของสาขา

@ViewBuilder กำหนดข้อจำกัด: สูงสุด 10 องค์ประกอบ ต่อบล็อก (ข้อจำกัด TupleView) หากคุณต้องการรวบรวมมากกว่าสิบองค์ประกอบ ให้ใช้ Group, ForEach หรือแบ่งเป็นส่วนประกอบย่อย ข้อจำกัดนี้มีอยู่เพราะ Swift สร้างการโอเวอร์โหลด buildBlock แยกต่างหากสำหรับจำนวนอาร์กิวเมนต์ตั้งแต่ 1 ถึง 10

องค์ประกอบ View และตัวปรับแต่ง

องค์ประกอบ (Composition) เป็นหลักการสำคัญของ SwiftUI: อินเทอร์เฟซที่ซับซ้อนถูกสร้างขึ้นจากส่วนประกอบ View ขนาดเล็กที่นำกลับมาใช้ใหม่ได้ แต่ละส่วนประกอบใช้โปรโตคอล View และรับผิดชอบส่วนของหน้าจอของตน ตัวปรับแต่ง (font, padding, foregroundColor) ถูกนำไปใช้กับ View และส่งคืน View ใหม่ที่มีการตั้งค่าที่เปลี่ยนแปลง

ตัวปรับแต่งใน SwiftUI ไม่ใช่การกลายพันธุ์ แต่เป็นการสร้างตัวห่อใหม่รอบ View ดั้งเดิม ตัวปรับแต่งแต่ละตัวส่งคืนชนิดใหม่ (ModifiedContent) ทำให้ SwiftUI สามารถสร้าง ทรีตัวปรับแต่ง และวาดเฉพาะส่วนที่เปลี่ยนแปลงอย่างมีประสิทธิภาพ ลำดับของการใช้ตัวปรับแต่งมีความสำคัญ: ลำดับที่แตกต่างกันให้ผลลัพธ์ทางภาพที่แตกต่างกัน

swift
Text("Hello, SwiftUI!")
    .font(.title)        // ModifiedContent
    .padding()           // ModifiedContent<..., PaddingModifier>
    .background(.yellow) // ModifiedContent<..., BackgroundModifier>
    .cornerRadius(8)    // ModifiedContent<..., CornerRadiusModifier>

การปรับแต่งประสิทธิภาพ: SwiftUI ไม่ได้เปรียบเทียบค่ารูปธรรมของ View แต่เปรียบเทียบเอกลักษณ์ผ่านกลไกเอกลักษณ์ (id, ForEach, เอกลักษณ์ที่เสถียรของโครงสร้าง) ถ้าโครงสร้างของ View ไม่เปลี่ยนแปลง — body จะไม่ถูกเรียก ซึ่งทำได้ผ่านการเปรียบเทียบ Equatable และกลไก PreferenceKey สำหรับส่งข้อมูลขึ้นไปในลำดับชั้น

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

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

View Protocol ใน SwiftUI คืออะไร?

View Protocol เป็นโปรโตคอลพื้นฐานของ SwiftUI ที่ส่วนประกอบที่แสดงใดๆ ต้องปฏิบัติตาม มันต้องการคุณสมบัติ body ที่คำนวณได้เพียงอย่างเดียวที่ส่งคืนเนื้อหา องค์ประกอบ SwiftUI มาตรฐานทั้งหมด — Text, Button, Image, VStack — ใช้โปรโตคอลนี้

ทำไม View ใน SwiftUI ต้องเป็น struct และไม่ใช่ class?

SwiftUI ใช้ ความหมายของค่า (value semantics) สำหรับการอัปเดตอินเทอร์เฟซที่คาดเดาได้ โครงสร้างไม่มีสถานะที่เปลี่ยนแปลงได้ร่วมกัน ซึ่งช่วยให้ SwiftUI สามารถเปรียบเทียบลำดับชั้น View เก่าและใหม่ได้อย่างมีประสิทธิภาพและวาดเฉพาะองค์ประกอบที่เปลี่ยนแปลง คลาสทำลายการปรับแต่งนี้

คุณสมบัติ body ของโปรโตคอล View ส่งคืนอะไร?

body ส่งคืน some View — ชนิดทึบแสงที่ซ่อนการใช้งานรูปธรรม จริงๆ แล้วมันส่งคืนชนิดใดก็ได้ที่ปฏิบัติตาม View: Text, Image, VStack, โครงสร้างกำหนดเอง คอมไพเลอร์กำหนดชนิดรูปธรรมในเวลาคอมไพล์เพื่อการปรับแต่ง

ความแตกต่างระหว่าง some View และ AnyView คืออะไร?

some View เป็นชนิดทึบแสงที่มีชนิดรูปธรรมถูกกำหนดในเวลาคอมไพล์ AnyView คือการลบชนิด (type erasure) ที่ห่อ View ใดๆ ในคอนเทนเนอร์เดียว some View มีประสิทธิภาพมากกว่า AnyView เพิ่มค่าใช้จ่ายและใช้เฉพาะเมื่อต้องการการเปลี่ยนชนิดแบบไดนามิก

สามารถวาง Views ได้กี่ตัวในบล็อก @ViewBuilder หนึ่งบล็อก?

สูงสุด 10 องค์ประกอบ — นี่คือข้อจำกัดของ TupleView ซึ่งสร้าง buildBlock สำหรับจำนวนอาร์กิวเมนต์ตั้งแต่ 1 ถึง 10 หากคุณต้องการองค์ประกอบมากขึ้น ให้ใช้ Group, ForEach, List หรือแบ่งเป็นส่วนประกอบย่อย ข้อจำกัดนี้มีอยู่ในระดับคอมไพเลอร์ Swift

สรุป

  • View Protocol เป็นรากฐานของ SwiftUI: องค์ประกอบที่แสดงใดๆ ต้องปฏิบัติตามโปรโตคอลนี้
  • body เป็นคุณสมบัติที่จำเป็นเพียงอย่างเดียว ซึ่งส่งคืนเนื้อหาผ่านชนิดทึบแสง some View
  • some View เป็นชนิดทึบแสงที่ช่วยให้คอมไพเลอร์ปรับลำดับชั้น View ให้เหมาะสม
  • @ViewBuilder เป็น result builder สำหรับรวบรวมหลาย Views ในบล็อกเดียวโดยไม่ต้องมีตัวเก็บเพิ่มเติม
  • View เป็นชนิดค่า (struct) เสมอ ซึ่งรับประกันการอัปเดตที่คาดเดาได้และ diffing
  • ตัวปรับแต่ง ไม่ได้เปลี่ยน View แต่สร้างตัวห่อ ModifiedContent ใหม่
  • องค์ประกอบของส่วนประกอบ View ขนาดเล็กเป็นรูปแบบหลักของสถาปัตยกรรม SwiftUI

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

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

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

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