@ObservedObject: คืออะไร, ทำงานอย่างไรและตัวอย่าง

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

@ObservedObject คือ Property Wrapper ใน SwiftUI สำหรับสังเกตอินสแตนซ์ ObservableObject ที่ถูกส่งมาจากภายนอก แตกต่างจาก @StateObject ตรงที่ @ObservedObject ไม่ได้สร้างวัตถุใหม่ — มันสมัครรับการเปลี่ยนแปลงของวัตถุที่มีอยู่แล้ว ตาม เอกสารสำหรับนักพัฒนา Apple (2025), @ObservedObject ถูกใช้ในวิวย่อยที่ต้องการติดตามข้อมูลที่เป็นของวิวหลัก @ObservedObject ให้การเชื่อมต่อแบบรีแอกทีฟโดยไม่ต้องจัดการวงจรชีวิตของวัตถุ

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

  • @ObservedObject — Property Wrapper สำหรับสังเกต ObservableObject โดยไม่เป็นเจ้าของ
  • ไม่สร้างใหม่ — วัตถุถูกส่งมาจากวิวหลักหรือสภาพแวดล้อม
  • @Published — คุณสมบัติภายใน ObservableObject ที่ SwiftUI ติดตามการเปลี่ยนแปลง
  • วาดใหม่ — เมื่อคุณสมบัติ @Published เปลี่ยนแปลง SwiftUI จะอัปเดตวิวที่สมัครรับทั้งหมด
  • อย่าสับสนกับ @StateObject — @ObservedObject ไม่รับประกันอินสแตนซ์เดียว

@ObservedObject ใน SwiftUI คืออะไร?

@ObservedObject คือ Property Wrapper ที่สมัครวิวให้รับการเปลี่ยนแปลงของ ObservableObject ObservableObject คือโปรโตคอลจากเฟรมเวิร์ก Combine ที่ต้องการการใช้งาน publisher objectWillChange เมื่อคุณสมบัติใดๆ ที่ถูกทำเครื่องหมายด้วย @Published เปลี่ยนแปลงภายใน ObservedObject publisher จะส่งสัญญาณ และ SwiftUI จะวาดวิวทั้งหมดที่สมัครรับผ่าน @ObservedObject ใหม่

คุณสมบัติหลักของ @ObservedObject คือ การไม่เป็นเจ้าของ วิวไม่รับผิดชอบในการสร้างหรือทำลายวัตถุ วัตถุถูกสร้างขึ้นในวิวหลัก (ผ่าน @StateObject) หรือถูกฉีดผ่าน @EnvironmentObject วิวย่อยเพียงสังเกตการเปลี่ยนแปลงและรับการอัปเดต หากวัตถุถูกแทนที่ในวิวหลัก @ObservedObject จะสลับไปยังอินสแตนซ์ใหม่

@ObservedObject เหมาะสำหรับ สถานการณ์การแชร์ข้อมูล: โมเดลผู้ใช้ การตั้งค่าร่วมกัน สถานะการเชื่อมต่อเซิร์ฟเวอร์ เมื่อวิวหลายแห่งในระดับลำดับชั้นต่างกันจำเป็นต้องแสดงข้อมูลเดียวกัน @ObservedObject ในแต่ละวิวจะสร้างการสมัครรับที่เป็นอิสระแต่สอดคล้องกันไปยังแหล่งข้อมูลเดียว

@ObservedObject vs @StateObject: ความแตกต่างหลัก

ความแตกต่างระหว่าง @ObservedObject และ @StateObject เป็นหนึ่งในหัวข้อที่พบบ่อยที่สุดในการสัมภาษณ์ SwiftUI กฎหลัก: @StateObject สร้างและเป็นเจ้าของวัตถุ @ObservedObject สังเกตวัตถุที่มีอยู่แล้ว การละเมิดกฎนี้ทำให้เกิดการสูญเสียข้อมูลที่ไม่คาดคิดหรือการเริ่มต้นซ้ำซ้อน

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

@StateObject รับประกันว่าวัตถุจะถูกสร้างครั้งเดียวและอยู่รอดจากการเริ่มต้นซ้ำของโครงสร้างวิว @ObservedObject รับวัตถุจากภายนอกและถูกสร้างใหม่ทุกครั้งที่มีการเริ่มต้นโครงสร้างหลัก หากวิวหลักใช้ @StateObject สำหรับวัตถุ วิวย่อยสามารถใช้ @ObservedObject ได้อย่างปลอดภัย — วัตถุจะไม่ซ้ำกันทั่วทั้งลำดับชั้น

@ObservedObject ติดตามการเปลี่ยนแปลงอย่างไร

กลไกการติดตามของ @ObservedObject ขึ้นอยู่กับ Combine และโปรโตคอล ObservableObject ในระหว่างการเริ่มต้น SwiftUI จะเรียก publisher objectWillChange — วัตถุต้องปล่อยสัญญาณก่อนที่จะเปลี่ยนแปลงคุณสมบัติ @Published Combine ส่งสัญญาณไปยังกราฟการพึ่งพาของ SwiftUI ซึ่งทำเครื่องหมายวิวที่ขึ้นอยู่ทั้งหมดว่าต้องการการอัปเดต สิ่งนี้เกิดขึ้นแบบซิงโครนัสก่อนที่ค่าจะเปลี่ยนแปลง

swift
class WeatherService: ObservableObject {
    @Published var temperature: Double = 22.0
    @Published var city: String = "Moscow"
}

struct WeatherView: View {
    @ObservedObject var weather: WeatherService

    var body: some View {
        VStack {
            Text("\(weather.city)")
            Text("\(weather.temperature)°C")
        }
    }
}

ในตัวอย่าง WeatherService คือ ObservableObject ที่มีคุณสมบัติ @Published สองรายการ WeatherView ประกาศ @ObservedObject var weather: WeatherService โดยรับอินสแตนซ์จากวิวหลัก เมื่อ temperature เปลี่ยนแปลง objectWillChange จะถูกเรียกก่อนที่จะตั้งค่าใหม่ SwiftUI จะวาด WeatherView ใหม่และแสดงอุณหภูมิจริง การสมัครรับถูกจัดการโดยอัตโนมัติโดย SwiftUI — นักพัฒนาไม่จำเป็นต้องเรียก sink หรือ dispose

รูปแบบการใช้งาน @ObservedObject

รูปแบบแรกคือ การส่งโมเดลผ่านตัวเริ่มต้น วิวหลักสร้าง ObservableObject ผ่าน @StateObject และส่งไปยังวิวย่อยเป็น @ObservedObject นี่คือการถ่ายโอนข้อมูลตามลำดับชั้นมาตรฐานที่วิวรากจัดการวงจรชีวิตของโมเดลและคอมโพเนนต์ที่ซ้อนกันทั้งหมดสมัครรับการเปลี่ยนแปลง

รูปแบบที่สองคือ EnvironmentObject เวอร์ชันทั่วโลกของ @ObservedObject ผ่านสภาพแวดล้อม SwiftUI วัตถุถูกฉีดที่ระดับซีนหรือวิวรากและพร้อมใช้งานโดยอัตโนมัติสำหรับคอมโพเนนต์ย่อยทั้งหมดโดยไม่ต้องส่งอย่างชัดเจนผ่านตัวเริ่มต้น ภายในวิวย่อย @EnvironmentObject ทำงานคล้ายกับ @ObservedObject แต่รับวัตถุจากสภาพแวดล้อม

รูปแบบที่สามคือ การรวม ObservableObject หลายตัว ในแอปพลิเคชันที่ซับซ้อน วิวสามารถสังเกตวัตถุหลายตัว: @ObservedObject var user: UserService, @ObservedObject var network: NetworkMonitor สิ่งนี้แยกความรับผิดชอบระหว่างบริการและรักษาความสามารถในการทดสอบของแต่ละคอมโพเนนต์

swift
struct DashboardView: View {
    @ObservedObject var user: UserViewModel
    @ObservedObject var network: NetworkMonitor

    var body: some View {
        VStack {
            Text("Welcome, \(user.name)")
            HStack {
                Circle()
                    .fill(network.isConnected ? Color.green : Color.red)
                    .frame(width: 10, height: 10)
            }
        }
    }
}

DashboardView สังเกต UserViewModel และ NetworkMonitor แต่ละวัตถุจัดการโดเมนข้อมูลของตนเองและแจ้งวิวอย่างอิสระเกี่ยวกับการเปลี่ยนแปลง หากเครือข่ายตัดการเชื่อมต่อ NetworkMonitor จะเปลี่ยน isConnected และ SwiftUI จะวาด DashboardView ใหม่ อัปเดตสีของตัวบ่งชี้ การรวม ObservableObject เป็นวิธีที่ต้องการในการจัดระเบียบข้อมูลในแอปพลิเคชัน SwiftUI

@Published: การเชื่อมต่อระหว่าง ObservableObject และ SwiftUI

@Published คือ Property Wrapper จาก Combine ที่เพิ่ม publisher โดยอัตโนมัติให้กับคุณสมบัติภายใน ObservableObject เมื่อคุณสมบัติ @Published เปลี่ยนแปลง Combine จะสร้างเหตุการณ์ผ่าน publisher objectWillChange SwiftUI สมัครรับ publisher นี้เมื่อใช้ @ObservedObject หรือ @StateObject และวาดวิวใหม่ทุกครั้งที่มีค่าใหม่

@Published รองรับ ทุกประเภท รวมถึงตัวเลือก คอลเล็กชัน และโครงสร้างที่กำหนดเอง อย่างไรก็ตาม สำหรับคอลเล็กชัน (อาร์เรย์, ดิกชันนารี) SwiftUI จะติดตามเฉพาะการแทนที่การอ้างอิง ไม่ใช่การเปลี่ยนแปลงเนื้อหา ในการตรวจจับการเพิ่มหรือลบองค์ประกอบ คุณต้องกำหนดคอลเล็กชันทั้งหมดใหม่หรือใช้ ObservableObject พร้อม objectWillChange.send() ด้วยตนเอง

รายละเอียดสำคัญ: @Published ควรใช้ภายในคลาสที่ใช้งาน ObservableObject เท่านั้น การใช้ @Published นอก ObservableObject จะทำให้เกิดข้อผิดพลาดในการคอมไพล์ นอกจากนี้ @Published ไม่สามารถใช้กับคุณสมบัติการเริ่มต้นแบบขี้เกียจ (lazy var) หรือคุณสมบัติที่คำนวณได้

ข้อผิดพลาดทั่วไปกับ @ObservedObject

ข้อผิดพลาดที่สำคัญที่สุดคือการใช้ @ObservedObject เพื่อสร้างวัตถุ หากคุณเขียน @ObservedObject var model = UserViewModel() ในวิวหลัก ทุกครั้งที่เรนเดอร์จะสร้างอินสแตนซ์ UserViewModel ใหม่ ข้อมูลจะสูญหายและการสมัครรับ @Published จะถูกสร้างขึ้นใหม่ ใช้ @StateObject สำหรับการสร้างเสมอ และใช้ @ObservedObject เพื่อรับวัตถุสำเร็จรูปเท่านั้น

ข้อผิดพลาดที่สองคือ การแก้ไขคุณสมบัติ @Published นอกเธรดหลัก ObservableObject ใช้ Combine ซึ่งต้องการส่งการเปลี่ยนแปลงบนเธรดหลัก (main actor) หากคุณเปลี่ยน @Published ในคิวพื้นหลัง SwiftUI อาจวาดวิวใหม่ในเวลาที่ไม่เหมาะสม ทำให้เกิด race conditions ใช้ DispatchQueue.main.async หรือ @MainActor สำหรับการอัปเดต

ปัญหาที่สามคือ การอัปเดตแบบวนซ้ำ หากการเปลี่ยนแปลง @Published ทำให้เกิดผลข้างเคียงที่เปลี่ยนแปลง @Published อีกครั้ง จะเกิดการวนซ้ำการวาดใหม่ไม่มีที่สิ้นสุด วิธีแก้ไข: ใช้แฟล็กป้องกัน (isUpdating) หรือแยกตรรกะไปยัง ObservableObject ต่างๆ ที่มีขอบเขตความรับผิดชอบชัดเจน

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

@ObservedObject สามารถเป็นตัวเลือกได้หรือไม่?

ได้ SwiftUI รองรับ @ObservedObject var model: UserViewModel? อย่างไรก็ตาม วิวจะไม่สมัครรับการเปลี่ยนแปลงในขณะที่วัตถุเป็น nil เมื่อกำหนดค่า การสมัครรับจะเปิดใช้งานโดยอัตโนมัติ

@ObservedObject แตกต่างจาก @EnvironmentObject อย่างไร?

@ObservedObject รับวัตถุผ่านตัวเริ่มต้น @EnvironmentObject รับผ่านสภาพแวดล้อม SwiftUI @EnvironmentObject ไม่ต้องการการส่งอย่างชัดเจนผ่านคอนสตรัคเตอร์ แต่วัตถุต้องถูกฉีดที่ระดับสูงสุดของลำดับชั้น

จะแจ้ง SwiftUI ด้วยตนเองเกี่ยวกับการเปลี่ยนแปลง ObservableObject ได้อย่างไร?

เรียก objectWillChange.send() ก่อนที่จะเปลี่ยนคุณสมบัติ สิ่งนี้มีประโยชน์เมื่อ @Published ไม่เหมาะสม (เช่น สำหรับคุณสมบัติที่คำนวณได้หรือการดำเนินการกับคอลเล็กชันที่คุณต้องรายงานการเปลี่ยนแปลงก่อนการกลาย)

ทำไม @ObservedObject ไม่วาดวิวใหม่เมื่อเปลี่ยนแปลงภายในอาร์เรย์?

@ObservedObject และ @Published ติดตามการแทนที่การอ้างอิง ไม่ใช่การเปลี่ยนแปลงเนื้อหาคอลเล็กชัน เพื่อกระตุ้นการวาดใหม่ คุณต้องกำหนดอาร์เรย์ใหม่: items.append(newItem) → items = items หรือใช้ objectWillChange.send() ก่อนการกลาย

สามารถใช้ @ObservedObject ใน struct ที่ไม่ได้ใช้งาน View ได้หรือไม่?

ไม่ได้ @ObservedObject คือ Property Wrapper ของ SwiftUI ที่ใช้ได้เฉพาะภายในประเภทที่ใช้งานโปรโตคอล View สำหรับ struct ทั่วไป ให้ใช้ Combine โดยตรงกับ ObservableObjectPublisher

สรุป

  • @ObservedObject — Property Wrapper สำหรับสังเกต ObservableObject โดยไม่เป็นเจ้าของ
  • @StateObject — สร้างวัตถุ, @ObservedObject — สังเกตวัตถุที่มีอยู่
  • @Published — publisher อัตโนมัติสำหรับคุณสมบัติ ObservableObject
  • การสมัครรับ — SwiftUI จัดการการสมัครรับ Combine โดยอัตโนมัติเมื่อใช้ @ObservedObject
  • การรวม — วิวสามารถสังเกต ObservableObject หลายตัวพร้อมกันได้
  • Main actor — คุณสมบัติ @Published ควรเปลี่ยนบนเธรดหลักเท่านั้น
  • EnvironmentObject — ทางเลือกของ @ObservedObject สำหรับการส่งโดยนัยผ่านสภาพแวดล้อม

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

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

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

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