swiftView and Modifier

View และ Modifier ใน SwiftUI: กรอบแนวคิดเชิงประกาศและการประกอบส่วนติดต่อผู้ใช้

การออกแบบส่วนติดต่อผู้ใช้ในระบบซอฟต์แวร์สมัยใหม่ไม่ได้เป็นเพียงแค่การจัดองค์ประกอบด้านความสวยงามหรือการจัดวางข้อมูลบนหน้าจอเท่านั้น หากแต่เป็นโครงสร้างที่สะท้อนวิธีคิด วิธีการออกแบบ และแนวคิดเชิงสถาปัตยกรรมของระบบโดยรวม โดยเฉพาะในบริบทของแอปพลิเคชันที่ต้องรองรับความหลากหลายของอุปกรณ์ บริบทการใช้งาน และความเปลี่ยนแปลงของข้อมูลอย่างต่อเนื่อง ด้วยเหตุนี้ การออกแบบ UI จึงกลายเป็นปัญหาเชิงโครงสร้าง (structural problem) มากกว่าปัญหาเชิงการนำเสนอ (presentation problem)

SwiftUI นำเสนอแนวคิดการออกแบบส่วนติดต่อผู้ใช้แบบเชิงประกาศ (Declarative UI) ซึ่งเปลี่ยนบทบาทของนักพัฒนาจากการกำหนดขั้นตอนการวาดและการอัปเดต UI ไปสู่ การระบุสิ่งที่ต้องการให้ปรากฏบนหน้าจอ ภายใต้เงื่อนไขของข้อมูลในขณะนั้น แนวคิดดังกล่าวไม่ได้เป็นเพียงการเปลี่ยนเครื่องมือหรือไวยากรณ์ของภาษาโปรแกรม แต่เป็นการเปลี่ยนกรอบความคิด (paradigm shift) ในการออกแบบซอฟต์แวร์และการพัฒนา UI อย่างมีนัยสำคัญ

แนวคิดพื้นฐานสองประการที่มีบทบาทสำคัญอย่างยิ่งใน SwiftUI คือ View และ Modifier โดย View ใน SwiftUI ไม่ได้หมายถึงหน้าจอหรือองค์ประกอบกราฟิกที่มีตัวตนถาวรบนหน้าจอ แต่เป็น โครงสร้างข้อมูลเชิงนามธรรมที่ทำหน้าที่อธิบายลักษณะของส่วนติดต่อผู้ใช้ในช่วงเวลาหนึ่ง ขณะที่ Modifier ทำหน้าที่เป็นกลไกในการแปลง View หนึ่งไปสู่อีก View หนึ่งที่มีคุณลักษณะเพิ่มเติม การทำความเข้าใจแนวคิดทั้งสองในระดับเชิงโครงสร้างจึงเป็นรากฐานสำคัญก่อนการเรียนรู้หัวข้ออื่น ๆ ใน SwiftUI

View ใน SwiftUI เป็นคำอธิบายเชิงโครงสร้างของส่วนติดต่อผู้ใช้ (UI)

ใน SwiftUI คำว่า View เป็นแนวคิดที่แตกต่างอย่างมีนัยสำคัญจากความหมายของ “หน้าจอ” หรือ “วิดเจ็ต” ที่เราอาจคุ้นเคยจากเฟรมเวิร์กเชิงสั่งการ เช่น UIKit หรือระบบ GUI แบบดั้งเดิม ในบริบทของ SwiftUI นั้น View ไม่ได้หมายถึงวัตถุที่มีตัวตนถาวรบนหน้าจอ และไม่ได้เป็นองค์ประกอบที่ถูกสร้างขึ้นหนึ่งครั้งแล้วคงอยู่ตลอดอายุการทำงานของแอปพลิเคชัน หากแต่เป็นคำอธิบายเชิงโครงสร้างของ UI ในช่วงเวลาหนึ่งเท่านั้น

พิจารณาโค้ดพื้นฐานต่อไปนี้

struct ContentView: View {
    var body: some View {
        Text("Hello, SwiftUI")
    }
}

ในระดับไวยากรณ์ โค้ดนี้เป็นการประกาศโครงสร้าง (struct) ที่สอดคล้องกับ View protocol และมี property ชื่อ body ซึ่งคืนค่าเป็น some View อย่างไรก็ตาม ในเชิงแนวคิด ContentView นี้ไม่ได้สร้างหน้าจอ และไม่ได้สั่งให้ระบบวาดข้อความบนหน้าจอโดยตรง แต่ทำหน้าที่อธิบายว่า หากต้องแสดง UI สำหรับ ContentView หน้าจอควรประกอบด้วย Text ที่มีข้อความว่า ‘Hello, SwiftUI’

เมื่อทดลองเปลี่ยนข้อความภายใน Text("Hello, SwiftUI") เป็นค่าอื่น เช่น "SwiftUI View" และสังเกตการเปลี่ยนแปลงใน Preview จะพบว่า UI เปลี่ยนไปทันที โดยที่ไม่ได้เรียกคำสั่งใด ๆ เพื่อสั่งให้ UI อัปเดต การเปลี่ยนแปลงนี้เกิดจากการเปลี่ยน คำอธิบายของ View ไม่ใช่จากการควบคุมขั้นตอนการทำงานของ UI

คุณลักษณะสำคัญประการหนึ่งของ View ใน SwiftUI คือ View โดยตัวมันเองไม่เก็บสถานะ (state) กล่าวคือ View มีลักษณะคล้ายฟังก์ชันทางคณิตศาสตร์ที่ให้ผลลัพธ์เดิมเสมอเมื่อได้รับอินพุตเดิม จากตัวอย่าง ContentView จะให้คำอธิบายของ UI แบบเดียวกันทุกครั้งที่ถูกประเมินผล แนวคิดนี้เป็นพื้นฐานสำคัญที่ทำให้ SwiftUI สามารถอัปเดต UI ได้อย่างมีประสิทธิภาพ โดยเลือกปรับเฉพาะส่วนที่จำเป็น และรองรับการแสดงผลบนอุปกรณ์ที่มีลักษณะต่างกันได้โดยอัตโนมัติ

View ใน SwiftUI ในฐานะฟังก์ชันของข้อมูล (View as a Function of Data)

เมื่อเข้าใจแล้วว่า View เป็นคำอธิบายเชิงโครงสร้างของ UI ขั้นตอนสำคัญถัดไปคือการทำความเข้าใจว่า คำอธิบายของ View สามารถเปลี่ยนแปลงได้ตามข้อมูลที่ View ได้รับ แนวคิดนี้เรียกว่า View as a Function of Data และเป็นหัวใจของการออกแบบ UI แบบ Declarative เพื่อให้เห็นภาพแนวคิดนี้อย่างเป็นรูปธรรม ให้พิจารณาการปรับแก้ View เดิมโดยเพิ่มตัวแปร message เข้าไปดังนี้

struct ContentView: View {
    let message = "Hello, SwiftUI"
    var body: some View {
        Text(message)
    }
}

ในตัวอย่างนี้ message เป็นค่าคงที่ที่ถูกประกาศภายใน View และถูกนำมาใช้เป็นข้อมูลสำหรับสร้างคำอธิบายของ UI ผ่าน Text(message) แม้จะมีตัวแปรเพิ่มขึ้นมา แต่ View ยังคงทำหน้าที่เป็นคำอธิบายของ UI ไม่ได้เปลี่ยนบทบาทไปเป็นตัวควบคุมการทำงานของ UI แต่อย่างใด เมื่อเปลี่ยนค่าที่เก็บใน message จะเห็นว่า UI เปลี่ยนไปตามข้อมูล โดยไม่ต้องเรียกคำสั่งอัปเดตใด ๆ สิ่งนี้ตอกย้ำแนวคิดว่า UI ใน SwiftUI เป็นผลลัพธ์ของข้อมูลที่ถูกส่งเข้าสู่ View

จากตัวอย่างนี้ สามารถอธิบาย View ในเชิงนามธรรมได้ว่า

กล่าวคือ View ทำหน้าที่เสมือนฟังก์ชันที่รับข้อมูลเป็นอินพุต และคืนค่าคำอธิบายของ UI เป็นเอาต์พุต เมื่อข้อมูลเปลี่ยน ผลลัพธ์ของ UI ก็เปลี่ยนตาม แต่โครงสร้างของ View ยังคงเดิม

เพื่อขยายแนวคิดนี้ให้ชัดเจนยิ่งขึ้น ลองสร้าง View ใหม่ชื่อ MessageView และนำไปใช้ซ้ำหลายครั้งภายใน ContentView

จากโค้ดนี้จะเห็นได้ว่า MessageView ถูกเขียนเพียงครั้งเดียว แต่สามารถสร้าง UI ที่แตกต่างกันได้ตามค่าของ message ที่รับเข้ามา ความแตกต่างของ UI เกิดจาก ข้อมูล ไม่ใช่จากโค้ด View ที่แตกต่างกัน

เมื่อ View ลักษณะนี้ถูกนำมาประกอบเข้าด้วยกันผ่าน VStack จะเกิดโครงสร้างลำดับชั้นของ View ที่เรียกว่า View Hierarchy โดย VStack ทำหน้าที่กำหนดความสัมพันธ์เชิงโครงสร้างระหว่าง View ย่อยทั้งหมด UI ที่ปรากฏบนหน้าจอจึงเป็นผลลัพธ์ของการประเมิน View Hierarchy ทั้งระบบ ไม่ใช่ผลจากการเรียกใช้ View ทีละตัว

Modifier: กลไกการแปลง View ภายใต้แนวคิด Declarative UI

เมื่อเข้าใจแล้วว่า UI ใน SwiftUI เกิดจากการประกอบ View หลายตัวเข้าด้วยกันเป็น View Hierarchy โดยที่ View แต่ละตัวสามารถอธิบายได้ในฐานะฟังก์ชันของข้อมูล อย่างไรก็ตาม การออกแบบ UI ในทางปฏิบัติไม่ได้หยุดอยู่เพียงการจัดโครงสร้างของ View เท่านั้น หากแต่ต้องสามารถ ปรับเปลี่ยนลักษณะ รูปแบบ และพฤติกรรมของ View เหล่านั้นได้อย่างยืดหยุ่น โดยไม่ทำลายโครงสร้างที่ออกแบบไว้ กลไกที่ทำหน้าที่ดังกล่าวใน SwiftUI คือ Modifier

ในกรอบความคิดแบบเชิงสั่งการ (Imperative UI) การปรับแต่ง UI มักเกิดจากการเรียกคำสั่งเพื่อเปลี่ยนสถานะของวัตถุ เช่น การเปลี่ยนสี การเปลี่ยนขนาด หรือการตั้งค่า property ของวิดเจ็ตเดิม อย่างไรก็ตาม SwiftUI ไม่ได้ทำงานในลักษณะนั้น Modifier ใน SwiftUI ไม่ได้ทำหน้าที่แก้ไข View เดิม แต่ทำหน้าที่ แปลง View หนึ่งไปสู่อีก View หนึ่งที่มีคุณลักษณะเพิ่มเติม

พิจารณาตัวอย่างพื้นฐานต่อไปนี้

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

แนวคิดนี้สอดคล้องกับคุณสมบัติ immutability ของ View โดย View ไม่ได้ถูกเปลี่ยนแปลงค่าภายในของมันเอง แต่เมื่อข้อมูลเปลี่ยน ระบบจะสร้างคำอธิบายของ View ใหม่ แทนการแก้ไข View เดิม แนวทางนี้ทำให้ SwiftUI สามารถพิจารณาได้อย่างชัดเจนว่า UI ควรเปลี่ยนตรงจุดใด และอัปเดตเฉพาะส่วนที่จำเป็นได้อย่างมีประสิทธิภาพ ซึ่งเป็นพื้นฐานสำคัญของการออกแบบส่วนติดต่อผู้ใช้แบบ Declarative

Modifier ในฐานะการประกอบของฟังก์ชัน (Function Composition)

Modifier ใน SwiftUI มักถูกใช้งานต่อเนื่องกันหลายตัว ซึ่งก่อให้เกิดโครงสร้างที่สามารถอธิบายได้ว่าเป็น การประกอบของฟังก์ชัน (function composition)

ในเชิงนามธรรม โค้ดข้างต้นสามารถอธิบายได้ดังนี้

โดย Modifier แต่ละตัวจะรับ View จากขั้นก่อนหน้าและสร้าง View ใหม่ที่มีคุณลักษณะเพิ่ม แล้วจึงส่ง View ใหม่นั้นต่อไปยัง Modifier ถัดไป ลักษณะการเขียนโค้ดเช่นนี้ช่วยให้โครงสร้างของ UI อ่านง่าย สื่อความหมายชัดเจน และสอดคล้องกับแนวคิดเชิงฟังก์ชันในวิทยาการคอมพิวเตอร์

ลำดับของ Modifier และผลต่อ View Hierarchy

เนื่องจาก Modifier ทำหน้าที่ห่อ (wrap) View เดิมไว้ ลำดับของ Modifier จึงมีผลโดยตรงต่อโครงสร้างของ View Hierarchy และผลลัพธ์ของ UI

พิจารณาสองตัวอย่างต่อไปนี้

และ

แม้จะใช้ Modifier ชุดเดียวกัน แต่ผลลัพธ์ที่ได้แตกต่างกันอย่างชัดเจน เนื่องจากลำดับของการห่อ View แตกต่างกัน ในเชิงโครงสร้าง

Modifier กับการแยกโครงสร้างออกจากลักษณะการแสดงผล

แนวคิดสำคัญอีกประการหนึ่งของ Modifier คือ การช่วยแยก โครงสร้างของ UI ออกจาก ลักษณะการแสดงผล อย่างชัดเจน

ในตัวอย่างนี้ VStack และ Text ทำหน้าที่กำหนดโครงสร้าง ขณะที่ .font(.headline) ทำหน้าที่กำหนดลักษณะการแสดงผล การแยกบทบาทเช่นนี้ช่วยให้โค้ดมีความยืดหยุ่น สามารถปรับเปลี่ยนรูปแบบ UI ได้โดยไม่กระทบโครงสร้าง

Modifier เป็นองค์ประกอบที่สะท้อนแนวคิด Declarative UI อย่างชัดเจน นักพัฒนาไม่ได้บอกระบบว่า ต้องวาดอย่างไร แต่บอกว่า View ควรมีคุณลักษณะใด จากนั้นระบบจะจัดการขั้นตอนการแสดงผลทั้งหมดให้โดยอัตโนมัติ หรือกล่าวโดยสรุปได้ว่า

  • View ระบุ โครงสร้าง

  • Modifier ระบุ คุณลักษณะ

  • ระบบจัดการ การแสดงผล

View Hierarchy และ Declarative UI

ในเชิงแนวคิด View Hierarchy ทำหน้าที่เป็นแบบจำลองเชิงโครงสร้าง (structural model) ของ UI ทั้งหมด โดย View แต่ละตัวไม่ได้เป็นวัตถุกราฟิกที่มีตัวตนถาวรบนหน้าจอ แต่เป็นค่าหนึ่ง (value) ที่ใช้ในการอธิบายว่า UI ควรมีลักษณะอย่างไรในบริบทของข้อมูล ณ ช่วงเวลาหนึ่ง การออกแบบ UI ใน SwiftUI จึงเปลี่ยนจากการควบคุมกระบวนการแสดงผลไปสู่การกำหนดโครงสร้างและความสัมพันธ์ขององค์ประกอบเชิงนามธรรม

View Hierarchy ใน SwiftUI สามารถอธิบายได้ด้วยแนวคิดโครงสร้างข้อมูลแบบต้นไม้ (tree data structure) ซึ่งเป็นแนวคิดพื้นฐานในวิทยาการคอมพิวเตอร์ โดยมี View ระดับบนสุดเป็นโหนดราก (root node) และมี View ย่อยเป็นโหนดลูกที่เชื่อมโยงกันเป็นลำดับชั้น พิจารณาตัวอย่างต่อไปนี้

จากโค้ดข้างต้น View Hierarchy สามารถอธิบายได้ว่า ContentView เป็น View ระดับบนสุด ภายในประกอบด้วย VStack ซึ่งทำหน้าที่เป็นโหนดโครงสร้างหลัก โดยมี Text("Profile") และ HStack เป็นโหนดลูก และภายใน HStack ยังมี Image และ Text เป็นโหนดลูกอีกชั้นหนึ่ง โครงสร้างเช่นนี้สะท้อนให้เห็นว่า UI ใน SwiftUI ไม่ได้ถูกมองเป็นภาพสองมิติ แต่เป็นโครงสร้างเชิงลำดับชั้นที่มีความสัมพันธ์อย่างชัดเจน

การตระหนักถึงบทบาทของ View Hierarchy มีความสำคัญต่อการออกแบบ UI ในเชิงสถาปัตยกรรม เนื่องจากช่วยส่งเสริมการแยกความรับผิดชอบของ View (separation of concerns) และการออกแบบแบบองค์ประกอบ (component-based design) View แต่ละตัวสามารถรับผิดชอบหน้าที่เฉพาะและถูกนำกลับมาใช้ซ้ำได้ในหลายบริบท แนวคิดนี้ยังสอดคล้องกับสถาปัตยกรรมแบบ Model–View–ViewModel (MVVM) ซึ่ง View ทำหน้าที่เป็นตัวแสดงผลจากข้อมูลและสถานะที่ถูกจัดการโดยชั้นอื่นของระบบ

การเชื่อมโยงสู่การเรียนรู้ภาคปฏิบัติ

จากบทความนี้ ผู้เรียนได้ทำความเข้าใจแนวคิดสำคัญของ SwiftUI ในเชิงโครงสร้าง ได้แก่ View ในฐานะคำอธิบายของส่วนติดต่อผู้ใช้ View ในฐานะฟังก์ชันของข้อมูล บทบาทของ Modifier ในการแปลง View และการประกอบ View ให้เกิดเป็น View Hierarchy ภายใต้แนวคิด Declarative UI แนวคิดเหล่านี้ช่วยเปลี่ยนกรอบความคิดจากการควบคุมการทำงานของ UI ไปสู่การอธิบายโครงสร้างของ UI จากข้อมูล

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

การฝึกปฏิบัติดังกล่าวมีเป้าหมายเพื่อให้ผู้เรียนสามารถอธิบายเหตุผลของโค้ดที่เขียนขึ้นได้อย่างมีหลักการ และเป็นพื้นฐานสำคัญสำหรับการเรียนรู้ในบทถัดไป ซึ่งจะกล่าวถึงการออกแบบ View ที่ปรับแต่งได้ด้วย Properties และการเชื่อมโยง UI เข้ากับข้อมูลและสถานะของระบบ

แนวทางในการจัดกิจกรรมการเรียนรู้

การต่อยอดการเรียนรู้

circle-info

รายละเอียดเพื่อการอ้างอิง ผู้เขียน ธิติ ธีระเธียร วันที่เผยแพร่ วันที่ 10 มกราคม 2569 วันที่ปรุงปรุงล่าสุด วันที่ 13 มกราคม 2569 เข้าถึงได้จาก https://ajthiti.gitbook.io/develop-in-swift/getting-started/view-and-modifierarrow-up-right เงื่อนใขในการใช้งาน This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Licensearrow-up-right.

arrow-up-right

Last updated