PreviewProvider — คืออะไร โพรโทคอล SwiftUI และการตั้งค่าใน Xcode

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

PreviewProvider เป็นโพรโทคอล SwiftUI ที่กำหนดจุดเริ่มต้นสำหรับสร้างพรีวิวใน Xcode Canvas การใช้งานโพรโทคอลช่วยให้นักพัฒนาเห็นอินเทอร์เฟซโดยไม่ต้องเปิดเครื่องจำลอง ช่วยเร่งการทำงานในขั้นตอนการจัดวาง ตามเอกสาร Apple Developer Documentation (2026) PreviewProvider เป็นสิ่งจำเป็นสำหรับ SwiftUI View ทั้งหมดหากโปรเจกต์ใช้ Canvas — หากไม่มี Canvas จะไม่แสดงอินเทอร์เฟซผู้ใช้ เรียนรู้เพิ่มเติมในบทความเกี่ยวกับ SwiftUI

หลักสำคัญ

  • PreviewProvider — โพรโทคอล SwiftUI สำหรับสร้างพรีวิว Xcode ใน Canvas
  • ข้อกำหนดเดียว — โพรโทคอลมีคุณสมบัติคำนวณเพียงอย่างเดียวคือ previews: some View
  • พรีวิวหลายรายการ — Group สามารถแสดงหลายสถานะของ View เดียวกัน
  • การกำหนดค่าอุปกรณ์ — previewDevice, previewLayout และ displayName กำหนดค่าการแสดงผล
  • ความเข้ากันได้กับ UIKit — UIViewRepresentable และ UIViewControllerRepresentable รองรับ PreviewProvider เช่นกัน

PreviewProvider คืออะไร?

PreviewProvider เป็นโพรโทคอล SwiftUI ที่กำหนดสัญญาสำหรับสร้างเนื้อหาพรีวิวใน Xcode Canvas โพรโทคอลมีคุณสมบัติที่จำเป็นหนึ่งอย่าง: previews ชนิด some View ค่าใดๆ ที่ previews ส่งคืนจะแสดงใน Canvas เป็นพรีวิวเชิงโต้ตอบ PreviewProvider ไม่ต้องการการสืบทอด — แค่การใช้งานแบบสแตติกใน extension ก็เพียงพอ

ในเชิงสถาปัตยกรรม PreviewProvider ไม่ได้เป็นส่วนหนึ่งของรันไทม์ SwiftUI — เป็นเพียงเครื่องมือสำหรับนักพัฒนาเท่านั้น โพรโทคอลถูกระบุด้วยแอตทริบิวต์ @available(iOS 13.0, *) และไม่ถูกคอมไพล์ในบิลด์รีลีส เนื่องจาก Xcode ใช้การคอมไพล์แบบมีเงื่อนไขเพื่อแยกโค้ดพรีวิวออกจากการผลิต ซึ่งหมายความว่า PreviewProvider ไม่ส่งผลกระทบต่อขนาดไบนารีหรือประสิทธิภาพของแอปพลิเคชัน

โพรโทคอล previews

คุณสมบัติ previews เป็นข้อกำหนดเดียวของ PreviewProvider โดยต้องส่งคืน View ใดๆ ก็ได้: จาก Text ธรรมดาไปจนถึงลำดับชั้นที่ซับซ้อนกับ Group และ ForEach Xcode เรนเดอร์ View ที่ส่งคืนใน Canvas โดยใช้การตั้งค่าระบบ (ธีม ขนาด ฟอนต์)

swift
import SwiftUI

struct GreetingView: View {
    let name: String
    
    var body: some View {
        Text("Hello, \(name)!")
            .padding()
    }
}

// PreviewProvider — static implementation
struct GreetingView_Previews: PreviewProvider {
    static var previews: some View {
        GreetingView(name: "World")
    }
}

ธรรมเนียมการตั้งชื่อ: Apple แนะนำให้ตั้งชื่อโครงสร้างพรีวิวเป็น {ViewName}_Previews ซึ่งไม่ใช่ข้อกำหนดของคอมไพเลอร์ แต่ช่วยเพิ่มความสามารถในการอ่านและการนำทางในโปรเจกต์ Xcode จะแทรกเทมเพลตนี้โดยอัตโนมัติเมื่อสร้างไฟล์ SwiftUI ใหม่

PreviewProvider ทำงานอย่างไร: โพรโทคอลและเมธอด previews

กลไกการทำงานของ PreviewProvider ขึ้นอยู่กับการจัดส่งแบบสแตติก: Xcode คอมไพล์ extension ของ PreviewProvider เฉพาะสำหรับการกำหนดค่า Debug และเรียก previews ในกระบวนการสร้าง Canvas ทุกครั้งที่โค้ดเปลี่ยนแปลง Xcode จะคอมไพล์เฉพาะ PreviewProvider ที่ถูกแก้ไขเท่านั้น ทำให้มั่นใจได้ว่าการอัปเดตพรีวิวเกือบจะทันที

SwiftUI ไม่รับประกันความตรงกันที่แน่นอนระหว่างพรีวิวและอินเทอร์เฟซผู้ใช้สุดท้ายบนเครื่องจำลองหรืออุปกรณ์ — Canvas ใช้การเรนเดอร์แบบง่าย แอนิเมชันที่มีความล่าช้าอาจแสดงไม่ถูกต้อง และส่วนประกอบ UIKit บางอย่าง (MapKit, WebView) จะไม่เรนเดอร์ใน Canvas หากไม่มีการกำหนดค่าเพิ่มเติม

พรีวิวหลายรายการผ่าน Group

Group ช่วยให้แสดงหลายสถานะของ View เดียวกันพร้อมกัน ช่วยเร่งการทำงานเมื่อจัดวางการกำหนดค่าต่างๆ แต่ละพรีวิวภายใน Group จะเรนเดอร์อย่างอิสระ

swift
struct ButtonView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ButtonView(title: "Primary", style: .primary)
                .previewDisplayName("Primary")
            
            ButtonView(title: "Disabled", style: .primary)
                .disabled(true)
                .previewDisplayName("Disabled")
            
            ButtonView(title: "Secondary", style: .secondary)
                .previewDisplayName("Secondary")
        }
    }
}

previewDisplayName เพิ่มป้ายกำกับให้แต่ละพรีวิวใน Canvas ซึ่งมีประโยชน์โดยเฉพาะเมื่อเปรียบเทียบหลายสถานะ จำนวนพรีวิวสูงสุดใน Group ไม่จำกัด แต่เกิน 6–8 จะทำให้ Canvas ช้าลง

การกำหนดค่าพรีวิวใน Xcode

Xcode มี ตัวปรับแต่งหลายตัวสำหรับกำหนดค่าการแสดงพรีวิว หลักๆ: previewDevice — จำลองอุปกรณ์เฉพาะ (iPhone 16 Pro, iPad Air, Apple Watch Ultra), previewLayout — กำหนดขนาด (device, fixed, sizeThatFits) การรวมกันของตัวปรับแต่งเหล่านี้ให้การควบคุมสภาพแวดล้อมพรีวิวอย่างสมบูรณ์

previewDevice รับสตริงที่มีชื่ออุปกรณ์ เช่น "iPhone 16 Pro" หรือ "iPad Pro 13-inch (M4)" รายการอุปกรณ์ที่มีขึ้นอยู่กับเครื่องจำลองที่ติดตั้งใน Xcode หากไม่พบอุปกรณ์ Canvas จะแสดงพรีวิวบนอุปกรณ์เริ่มต้นโดยไม่มีข้อผิดพลาด

ตัวปรับแต่งคำอธิบายตัวอย่าง
previewDeviceการจำลองอุปกรณ์.previewDevice("iPhone 16 Pro")
previewLayoutโหมดขนาด.previewLayout(.sizeThatFits)
previewDisplayNameป้ายกำกับพรีวิว.previewDisplayName("Dark Mode")
preferredColorSchemeโทนสี.preferredColorScheme(.dark)
dynamicTypeSizeขนาดฟอนต์.dynamicTypeSize(.xxxLarge)

พรีวิวสำหรับอุปกรณ์ต่างๆ

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

swift
struct AdaptiveView_Previews: PreviewProvider {
    static var previews: some View {
        ForEach(["iPhone SE (3rd generation)", "iPhone 16 Pro Max", "iPad Pro 13-inch (M4)"], id: \.self) { device in
            AdaptiveView()
                .previewDevice(.previewDevice(device))
                .previewDisplayName(device)
        }
    }
}

ตัวอย่าง PreviewProvider

ตัวอย่างเชิงปฏิบัติ แสดงสถานการณ์การใช้งาน PreviewProvider ที่หลากหลาย: ตั้งแต่พรีวิวธรรมดาไปจนถึงการกำหนดค่าที่ซับซ้อนกับข้อมูลจริงและความเข้ากันได้กับ UIKit

พรีวิวกับข้อมูลจำลอง

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

swift
struct UserProfileView: View {
    let user: User
    
    var body: some View {
        VStack {
            AsyncImage(url: user.avatarURL)
                .clipShape(Circle())
            Text(user.name)
                .font(.title)
            Text(user.bio)
                .font(.body)
                .foregroundColor(.secondary)
        }
    }
}

struct UserProfileView_Previews: PreviewProvider {
    static var previews: some View {
        UserProfileView(user: .mock)
            .previewDisplayName("Profile")
        
        UserProfileView(user: .mockLongName)
            .previewDisplayName("Long Name")
    }
}

พรีวิว UIKit ผ่าน UIViewRepresentable

ความเข้ากันได้กับ UIKit — PreviewProvider ทำงานกับส่วนประกอบ UIKit ที่ห่อใน UIViewRepresentable ด้วย ซึ่งช่วยให้พรีวิว UIKit View ที่มีอยู่ใน SwiftUI Canvas โดยไม่ต้องย้ายทั้งโปรเจกต์

swift
struct MapViewRepresentable: UIViewRepresentable {
    func makeUIView(context: Context) -> MKMapView {
        MKMapView()
    }
    
    func updateUIView(_ uiView: MKMapView, context: Context) {
        // Configure map
    }
}

struct MapView_Previews: PreviewProvider {
    static var previews: some View {
        MapViewRepresentable()
    }
}

PreviewProvider และ SwiftUI Canvas

Canvas เป็นตัวแก้ไขภาพของ Xcode ที่เรนเดอร์ผลลัพธ์ของ PreviewProvider แบบเรียลไทม์ หากไม่มีการใช้งาน PreviewProvider Canvas จะว่างเปล่า Canvas และ PreviewProvider ทำงานเป็นคู่: PreviewProvider กำหนดสิ่งที่แสดง Canvas กำหนดตำแหน่งและวิธีการ

สิ่งสำคัญคือต้องเข้าใจ: Canvas เป็นสภาพแวดล้อมการทำงานของพรีวิว ไม่ใช่ทางเลือกแทน PreviewProvider แม้ว่านักพัฒนาจะไม่เปิด Canvas ก็สามารถใช้ PreviewProvider เพื่อตรวจสอบโค้ดอย่างรวดเร็วผ่านพรีวิวป๊อปอัปเมื่อวางเมาส์เหนือไอคอน Canvas ตามข้อมูล WWDC 2024 Apple แนะนำให้เขียน PreviewProvider สำหรับทุก View เป็นมาตรฐานการพัฒนา คล้ายกับการเขียน unit test

ส่วนประกอบบทบาทความจำเป็น
PreviewProviderกำหนดเนื้อหาพรีวิวจำเป็นสำหรับ Canvas
Canvasเรนเดอร์พรีวิวในตัวแก้ไขเลือกได้ (สามารถใช้ .preview)
SwiftUI Viewส่วนประกอบ UIจำเป็น

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

ปัญหาทั่วไปกับ PreviewProvider

ปัญหา 1: พรีวิวไม่อัปเดต หาก Canvas ไม่สะท้อนการเปลี่ยนแปลงโค้ด สาเหตุมักมาจากแคช DerivedData ล้าง DerivedData ผ่าน Product → Clean Build Folder (⇧⌘K) หรือลบโฟลเดอร์ ~/Library/Developer/Xcode/DerivedData ด้วยตนเอง หลังจากทำความสะอาด Canvas จะสร้างพรีวิวใหม่ทั้งหมด

ปัญหา 2: PreviewProvider ไม่เห็น @StateObject PreviewProvider สร้างอินสแตนซ์แบบสแตติกของ View ดังนั้นการพึ่งพาที่ต้องการการฉีด (ViewModels, บริการ) ต้องถูกส่งผ่านตัวเริ่มต้นหรือ @StateObject พร้อมค่าเริ่มต้น ใช้วัตถุจำลองแทนบริการจริงในพรีวิว

ปัญหา 3: แอนิเมชันไม่ทำงานใน Canvas Canvas ไม่รองรับแอนิเมชัน SwiftUI ทั้งหมด — โดยเฉพาะที่ขึ้นอยู่กับเวลา (withAnimation ที่มีความล่าช้า, .spring) สำหรับการทดสอบแอนิเมชัน ให้รันแอปพลิเคชันบนเครื่องจำลอง Canvas เหมาะสำหรับการตรวจสอบเลย์เอาต์แบบสแตติก

การแก้ไข PreviewProvider กับการพึ่งพา

การฉีดการพึ่งพา เป็นวิธีที่ดีที่สุดในการทำให้ PreviewProvider ทำงานกับ ViewModels ที่ซับซ้อน สร้างอินสแตนซ์ ViewModel แยกต่างหากพร้อมข้อมูลทดสอบและส่งไปยังตัวเริ่มต้นของ View

swift
struct DashboardView: View {
    @StateObject var viewModel: DashboardViewModel
    
    var body: some View {
        List(viewModel.items) { item in
            Text(item.title)
        }
    }
}

struct DashboardView_Previews: PreviewProvider {
    static var previews: some View {
        DashboardView(viewModel: DashboardViewModel.mock)
    }
}

ส่วนขยายจำลอง: สร้าง extension สำหรับ ViewModel ที่ให้อินสแตนซ์ .mock แบบสแตติก ซึ่งเก็บข้อมูลทดสอบไว้ใกล้กับ ViewModel และทำให้ PreviewProvider อ่านง่าย

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

จำเป็นต้องเขียน PreviewProvider สำหรับทุก View หรือไม่?

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

ทำไม PreviewProvider ถึงแสดงข้อผิดพลาดการคอมไพล์?

PreviewProvider เพิ่มโค้ดเฉพาะในบิลด์ Debug ดังนั้นข้อผิดพลาดการคอมไพล์อาจเกิดขึ้นหากพรีวิวใช้ชนิดที่ไม่พร้อมใช้งานในการกำหนดค่ารีลีส ข้อผิดพลาดยังเกิดขึ้นเมื่อใช้ @available กับแพลตฟอร์มที่ไม่รองรับ Canvas หรือเมื่อเกินขีดจำกัดความซับซ้อนของพรีวิว

วิธีส่งข้อมูลจาก API ไปยัง PreviewProvider?

โดยตรง — ไม่สามารถทำได้ PreviewProvider ทำงานแบบแยกส่วน ใช้ข้อมูลจำลอง: สร้าง extension แบบสแตติกของโมเดลพร้อมอินสแตนซ์ .mock สำหรับ View ที่มี @StateObject ให้ส่ง ViewModel พร้อมข้อมูลทดสอบผ่านตัวเริ่มต้น ซึ่งจำลองข้อมูลจริงโดยไม่ต้องร้องขอเครือข่าย

PreviewProvider ส่งผลต่อขนาด IPA สุดท้ายหรือไม่?

ไม่ PreviewProvider ไม่ส่งผลต่อขนาดไบนารีรีลีส Xcode ใช้การคอมไพล์แบบมีเงื่อนไข (#if DEBUG / #if !RELEASE) เพื่อแยกโค้ดพรีวิวออกจากบิลด์รีลีส โค้ด PreviewProvider มีเฉพาะในการกำหนดค่า Debug และไม่เข้าไปในบิลด์ App Store

สามารถดีบัก PreviewProvider ใน Xcode ได้หรือไม่?

ได้ Xcode รองรับการดีบักพรีวิว ตั้ง breakpoint ภายใน previews หรือโค้ด View เองแล้วเลือก Product → Preview → Debug Preview breakpoint จะทำงานระหว่างการเรนเดอร์ Canvas ซึ่งมีประโยชน์สำหรับการวิเคราะห์ปัญหาเลย์เอาต์ที่มองเห็นได้เฉพาะในพรีวิว

สรุป

  • PreviewProvider — โพรโทคอล SwiftUI สำหรับสร้างพรีวิวใน Xcode Canvas ด้วยคุณสมบัติ previews เพียงอย่างเดียว
  • พรีวิวหลายรายการ — Group กับ ForEach ช่วยให้แสดงหลายสถานะของ View บนอุปกรณ์ต่างๆ
  • ตัวปรับแต่ง — previewDevice, previewLayout, preferredColorScheme และ dynamicTypeSize กำหนดค่าการแสดงผล
  • การแยกส่วน — PreviewProvider ทำงานเฉพาะในการกำหนดค่า Debug และไม่ส่งผลต่อขนาด IPA รีลีส
  • ข้อมูลจำลอง — สำหรับพรีวิวกับโมเดลที่ซับซ้อน ให้ใช้อินสแตนซ์ .mock แบบสแตติก
  • การรองรับ UIKit — ผ่าน UIViewRepresentable PreviewProvider ทำงานกับส่วนประกอบ UIKit เช่นกัน

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

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

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

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