ประเด็นสำคัญ
View Protocol คือโปรโตคอลหลักของ SwiftUI ต้องการคุณสมบัติเดียว: var body: some View body คือคุณสมบัติที่คำนวณแล้วซึ่งส่งคืนคำอธิบาย UI SwiftUI จะเรียก body ทุกครั้งที่สถานะเปลี่ยนแปลงและเรนเดอร์ผลลัพธ์บน GPU
@ViewBuilder คือ Result Builder สำหรับ View อนุญาตให้เขียนหลาย Views ภายใน closure โดยไม่ต้อง return และไม่มี TupleView รองรับ if/else, switch, ForEach คอนเทนเนอร์ทั้งหมด (VStack, HStack, ZStack, Group) ใช้ @ViewBuilder ทางเลือกอื่นคือ Group { … } สำหรับการจัดกลุ่มโดยไม่ต้องมีเลย์เอาต์ some View คือ Opaque Type คอมไพเลอร์รู้ประเภท View ที่เป็นรูปธรรม (Text, Button, VStack ฯลฯ) แต่ส่งคืนภายนอกเป็น some View ซึ่งช่วยให้เปลี่ยนประเภท body โดยไม่เปลี่ยนลายเซ็น ViewModifier — ตัวดัดแปลง View: .font(), .padding(), .background() ตัวดัดแปลงที่กำหนดเองผ่าน ViewModifier protocol และ .modifier()
// ตัวอย่าง View ด้วย @ViewBuilder และ NavigationStack
struct ContentView: View {
@State private var items = ["Item 1", "Item 2"]
var body: some View {
NavigationStack {
List(items, id: .self) { item in
NavigationLink(item) {
DetailView(item: item)
}
}
.navigationTitle("Items")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Add") {
items.append("New Item")
}
}
}
}
}
}
// DetailView ด้วย @StateObject
struct DetailView: View {
let item: String
@StateObject private var viewModel = DetailViewModel()
var body: some View {
Text(item)
.task {
await viewModel.loadDetails(for: item)
}
}
}NavigationStack (iOS 16+) — การนำทางที่ขับเคลื่อนด้วยข้อมูล รับเส้นทาง (อาร์เรย์ของค่าที่แฮชได้) และแสดงปลายทางผ่าน navigationDestination แทนที่ NavigationLink ด้วยวิวปลายทาง NavigationLink — ปุ่มสำหรับนำทางในสแต็ก List — รายการแนวตั้งพร้อมส่วนต่างๆ การปัด การลบ และการลากและวาง Form — List เฉพาะสำหรับการตั้งค่า: ส่วนต่างๆ ตัวเลือก สวิตช์ ฟิลด์ข้อความ Section — การจัดกลุ่มใน List/Form พร้อมส่วนหัวและส่วนท้าย ViewModifier — ตัวดัดแปลงที่กำหนดเองสำหรับการใช้สไตล์ซ้ำ .modifier(CustomModifier()) — การใช้งาน
List ใน SwiftUI เทียบเท่ากับ UITableView รองรับ .onDelete, .onMove, .refreshable SwipeActions — .swipeActions { Button("ลบ", role: .destructive) { } } Form — เพิ่มประสิทธิภาพสำหรับการตั้งค่า: DatePicker, Toggle, Stepper, Picker Section พร้อม header/footer — สำหรับการจัดกลุ่ม OutlineGroup — รายการแบบลำดับชั้น (เทียบเท่า UITableView พร้อมส่วนต่างๆ) DisclosureGroup — ส่วนที่ยุบได้พร้อมเนื้อหา IT Sectr แนะนำ List สำหรับข้อมูลและ Form สำหรับการตั้งค่า
PreviewProvider — โปรโตคอลสำหรับตัวอย่างใน Xcode Canvas Canvas — ตัวอย่าง SwiftUI แบบโต้ตอบ (ต้องการ @main และ Swift 5.9+) @ScaledMetric — ขนาดที่ปรับเปลี่ยนได้ซึ่งปรับขนาดตาม Dynamic Type
Property Wrappers คือพื้นฐานของการจัดการสถานะใน SwiftUI @State — สถานะท้องถิ่น (value type) @Binding — การเชื่อมต่อกับสถานะแม่ @StateObject — สร้าง ObservableObject SwiftUI จัดการวงจรชีวิตของออบเจกต์ @ObservedObject — สังเกต ObservableObject ภายนอก @EnvironmentObject — ออบเจกต์จากสภาพแวดล้อม (การฉีดการพึ่งพาผ่าน .environmentObject()) @Environment — ค่าระบบ (.colorScheme, .locale) @AppStorage — UserDefaults @FetchRequest — คำสั่ง Core Data @FocusState — โฟกัสอินพุต
| ตัวห่อ | วัตถุประสงค์ | ความเป็นเจ้าของ |
|---|---|---|
| @State | สถานะท้องถิ่น (value type) | View เป็นเจ้าของ |
| @Binding | การเชื่อมต่อกับสถานะแม่ | แม่เป็นเจ้าของ |
| @StateObject | สร้าง ObservableObject | View เป็นเจ้าของ |
| @ObservedObject | สังเกตออบเจกต์ภายนอก | เจ้าของภายนอก |
| @EnvironmentObject | ออบเจกต์จากสภาพแวดล้อม | บรรพบุรุษเป็นเจ้าของ |
| @Environment | ค่าระบบ | ระบบ |
| @AppStorage | UserDefaults | UserDefaults |
| @FocusState | โฟกัสอินพุต | View เป็นเจ้าของ |
@StateObject vs @ObservedObject: @StateObject สร้างออบเจกต์ @ObservedObject สังเกตมัน ใช้ @StateObject สำหรับการสร้างโมเดลครั้งแรกในลำดับชั้น @ObservedObject สำหรับส่งต่อให้วิวลูก @FocusState — การจัดการโฟกัส: .focused($field, equals: .email) รองรับ enum สำหรับหลายฟิลด์
@Environment — ค่าระบบ: colorScheme, locale, sizeCategory, layoutDirection, managedObjectContext ค่สภาพแวดล้อมที่กำหนดเอง — ค่าที่กำหนดเองผ่าน EnvironmentKey ใช้สำหรับการฉีดการพึ่งพา: ส่งบริการโดยไม่มีพารามิเตอร์ที่ชัดเจน ตัวดัดแปลง .environment() — ตั้งค่าในลำดับชั้น @EnvironmentObject — ObservableObject จาก .environmentObject() แตกต่างจาก @Environment ตรงที่ส่งประเภทอ้างอิง IT Sectr แนะนำ @Environment สำหรับค่าระบบและ @EnvironmentObject สำหรับบริการ
.task{} — การดำเนินการแบบอะซิงโครนัสเมื่อวิวปรากฏ การยกเลิกอัตโนมัติเมื่อหายไป แทนที่ .onAppear สำหรับ async/await .onAppear{} — การดำเนินการแบบซิงโครนัสเมื่อปรากฏ .onDisappear{} — การดำเนินการเมื่อหายไป .onChange(of:) — การตอบสนองต่อการเปลี่ยนแปลงค่า .onReceive(Publisher) — การตอบสนองต่อผู้เผยแพร่ Combine วงจรชีวิตของ View ใน SwiftUI: init → onAppear → body (การเรนเดอร์) → onDisappear เมื่อสถานะเปลี่ยน: body → diff → การเรนเดอร์ใหม่ IT Sectr แนะนำ .task สำหรับการโหลดแบบอะซิงโครนัสและ .onAppear สำหรับการวิเคราะห์
.animation() — ตัวดัดแปลงแอนิเมชัน .transition() — แอนิเมชันปรากฏ/หายไป withAnimation — แอนิเมชันการเปลี่ยนสถานะอย่างชัดแจ้ง matchedGeometryEffect — แอนิเมชันระหว่างวิวต่างๆ (hero animation) PhaseAnimator (iOS 17+) — แอนิเมชันหลายเฟสตาม enum KeyframeAnimator (iOS 17+) — แอนิเมชันทีละเฟรมด้วยคีย์เฟรม แอนิเมชัน SwiftUI ทำงานบน GPU ผ่าน Core Animation IT Sectr แนะนำ .spring() สำหรับแอนิเมชันที่เป็นธรรมชาติและ .interpolatingSpring สำหรับเอฟเฟกต์ทางกายภาพ
ObservableObject — โปรโตคอลสำหรับออบเจกต์ที่มีคุณสมบัติ @Published SwiftUI สมัครรับข้อมูลจากผู้เผยแพร่ objectWillChange @Published — เผยแพร่การเปลี่ยนแปลงคุณสมบัติ @StateObject — สร้าง ObservableObject จัดการวงจรชีวิต @ObservedObject — สังเกตภายนอก Combine — เฟรมเวิร์กสำหรับการเขียนโปรแกรมเชิงรับ @EnvironmentObject — DI ผ่านสภาพแวดล้อม .environmentObject() ตั้งค่า @EnvironmentObject อ่าน MVVM — สถาปัตยกรรมมาตรฐาน: View (SwiftUI) — ViewModel (ObservableObject) — Model IT Sectr แนะนำ MVVM + @StateObject สำหรับ ViewModel หลัก
class UserViewModel: ObservableObject {
@Published var users: [User] = []
@Published var isLoading = false
func loadUsers() async {
isLoading = true
defer { isLoading = false }
do {
users = try await api.fetchUsers()
} catch {
print("ข้อผิดพลาด: \(error)")
}
}
}
struct UsersView: View {
@StateObject private var viewModel = UserViewModel()
var body: some View {
List(viewModel.users, id: \.id) { user in
Text(user.name)
}
.task { await viewModel.loadUsers() }
.overlay {
if viewModel.isLoading { ProgressView() }
}
}
}การเข้าถึง ใน SwiftUI: .accessibilityLabel(), .accessibilityHint(), .accessibilityValue(), .accessibilityAddTraits() VoiceOver อ่านป้ายกำกับการเข้าถึง Dynamic Type — @ScaledMetric, @DynamicProperty การแปลภาษา: String(localized:) (SwiftUI + String Catalog) LocalizedStringKey — การแปลอัตโนมัติ กฎพหูพจน์ — ผ่าน String Catalog (one, few, many, other) จากขวาไปซ้าย (อาหรับ, ฮีบรู) — รองรับโดยอัตโนมัติ .environment(.layoutDirection, .rightToLeft) IT Sectr แนะนำป้ายกำกับการเข้าถึงสำหรับองค์ประกอบเชิงโต้ตอบทั้งหมด
struct AccessibleButton: View {
let action: () -> Void
var body: some View {
Button(action: action) {
Label("Settings", systemImage: "gear")
}
.accessibilityLabel("Open Settings")
.accessibilityHint("Double tap to navigate to settings screen")
.accessibilityAddTraits(.isButton)
}
}
// การรองรับ Dynamic Type
struct ScalableText: View {
@ScaledMetric private var fontSize: CGFloat = 17
var body: some View {
Text("Hello, World!")
.font(.system(size: fontSize))
}
}Swift Charts (iOS 16+) — เฟรมเวิร์กสำหรับสร้างแผนภูมิ Chart { } — คอนเทนเนอร์พื้นฐาน BarMark, LineMark, PointMark, AreaMark, RuleMark — เครื่องหมาย ForEach สำหรับข้อมูล ChartAxis — การปรับแต่งแกน .chartXAxis, .chartYAxis ChartLegend — คำอธิบาย การประมาณค่า — catmullRom, linear, step แอนิเมชัน — .animation() สำหรับ Chart IT Sectr แนะนำ Swift Charts สำหรับแผนภูมิในตัวและ Charts (DGCharts) สำหรับแผนภูมิที่ซับซ้อน
import Charts
struct MonthlySales: Identifiable {
let id = UUID()
let month: String
let sales: Double
}
struct SalesChart: View {
let data: [MonthlySales]
var body: some View {
Chart(data) { item in
BarMark(
x: .value("Month", item.month),
y: .value("Sales", item.sales)
)
.foregroundStyle(.blue.gradient)
}
.chartXAxisLabel("Month")
.chartYAxisLabel("Sales")
.frame(height: 200)
.padding()
}
}Swift Package Manager (SPM) — ตัวจัดการการพึ่งพาของ Apple รวมอยู่ใน Xcode รองรับ: แพ็กเกจไบนารี ทรัพยากร การทดสอบ swift-6 การทำงานพร้อมกันอย่างเคร่งครัด การเผยแพร่แพ็กเกจผ่าน GitHub ด้วยแท็ก semver SPM เป็นมาตรฐานโดยพฤตินัยสำหรับการพึ่งพา Swift แทนที่ CocoaPods และ Carthage IT Sectr แนะนำ SPM สำหรับโปรเจกต์ใหม่ทั้งหมด
Swift Concurrency (async/await, TaskGroup, AsyncSequence) — async/await สร้างใน Swift 5.5+ Task — หน่วยของอะซิงโครนี TaskGroup — งานแบบขนาน AsyncSequence — ลำดับแบบอะซิงโครนัส (AsyncStream, AsyncAlgorithms) Task Local Values — ข้อมูลบริบทสำหรับ Task Swift Concurrency แทนที่ Combine อย่างสมบูรณ์สำหรับการดำเนินการแบบอะซิงโครนัส
คำถามที่พบบ่อย
View Protocol คือโปรโตคอลพื้นฐาน ต้องการ var body: some View body คือคำอธิบาย UI ที่เรนเดอร์บน GPU
@ViewBuilder คือ Result Builder สำหรับหลาย Views อนุญาต if/else, switch, ForEach ภายในคอนเทนเนอร์
@StateObject สร้างออบเจกต์ @ObservedObject สังเกตออบเจกต์ที่มีอยู่ @StateObject สำหรับการสร้างครั้งแรกในลำดับชั้น
NavigationStack — การนำทางที่ขับเคลื่อนด้วยข้อมูล แบบ path-based, deep linking แทนที่ NavigationView
@FocusState — การจัดการโฟกัสอินพุต ตัวดัดแปลง .focused() รองรับ enum สำหรับหลายฟิลด์
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ