@ObservedObject: چیست، چگونه کار می‌کند و نمونه‌ها

نویسنده: IT Sectr منتشر شده: 2026-06-19 زمان مطالعه: 7 دقیقه

@ObservedObject یک Property Wrapper در SwiftUI برای مشاهده یک نمونه ObservableObject است که از خارج منتقل شده است. برخلاف @StateObject، @ObservedObject شیء را ایجاد نمی‌کند — آن در تغییرات شیء موجود مشترک می‌شود. به گفته Apple Developer Documentation (2025)، @ObservedObject در viewهای فرزندی استفاده می‌شود که نیاز به ردیابی داده‌های متعلق به والد دارند. @ObservedObject ارتباط واکنشی را بدون مدیریت چرخه عمر شیء فراهم می‌کند.

نکات اصلی

  • @ObservedObject — Property Wrapper برای مشاهده ObservableObject بدون مالکیت
  • بدون ایجاد — شیء از view والد یا محیط منتقل می‌شود
  • @Published — ویژگی‌های داخل ObservableObject که تغییرات آنها توسط SwiftUI ردیابی می‌شود
  • ترسیم مجدد — هنگام تغییر ویژگی @Published، SwiftUI همه viewهای مشترک را به‌روز می‌کند
  • با @StateObject اشتباه نگیرید — @ObservedObject یک نمونه واحد را تضمین نمی‌کند

@ObservedObject در SwiftUI چیست؟

@ObservedObject یک Property Wrapper است که view را در تغییرات ObservableObject مشترک می‌کند. ObservableObject پروتکلی از فریمورک Combine است که نیاز به پیاده‌سازی publisher objectWillChange دارد. زمانی که هر ویژگی مشخص شده با @Published در داخل ObservableObject تغییر کند، publisher سیگنال ارسال می‌کند و SwiftUI تمام viewهای مشترک شده از طریق @ObservedObject را دوباره ترسیم می‌کند.

ویژگی اصلی @ObservedObject عدم مالکیت است. View مسئول ایجاد یا نابودی شیء نیست. شیء در view والد (از طریق @StateObject) ایجاد می‌شود یا از طریق @EnvironmentObject تزریق می‌شود. View فرزند فقط تغییرات را مشاهده می‌کند و به‌روزرسانی‌ها را دریافت می‌کند. اگر شیء در والد جایگزین شود، @ObservedObject به نمونه جدید سوئیچ می‌کند.

@ObservedObject برای سناریوهای اشتراک داده مناسب است: مدل کاربر، تنظیمات مشترک، وضعیت اتصال به سرور. وقتی چندین view در سطوح مختلف سلسله‌مراتب باید داده‌های یکسانی را نمایش دهند، @ObservedObject در هر view اشتراک‌های مستقل اما هماهنگ به یک منبع ایجاد می‌کند.

@ObservedObject در مقابل @StateObject: تفاوت‌های کلیدی

تفاوت بین @ObservedObject و @StateObject یکی از رایج‌ترین موضوعات سوالات در مصاحبه‌های SwiftUI است. قانون اصلی: @StateObject شیء را ایجاد و مالک می‌شود، @ObservedObject شیء موجود را مشاهده می‌کند. نقض این قانون منجر به از دست رفتن غیرمنتظره داده یا مقداردهی اولیه مضاعف می‌شود.

ویژگی@StateObject@ObservedObject
ایجاد شیءبله، هنگام مقداردهی viewخیر، آماده دریافت می‌کند
مالکیتview فعلیکامپوننت والد
نمونه واحدبله، در کل چرخه عمرخیر، ممکن است جایگزین شود
ایجاد مجدد هنگام رندرخیر، حفظ می‌شودبستگی به والد دارد
کجا استفاده شودview ریشه مالکviewهای فرزند

@StateObject تضمین می‌کند که شیء یک بار ایجاد می‌شود و از مقداردهی‌های مجدد ساختار view جان سالم به در می‌برد. @ObservedObject شیء را از خارج دریافت می‌کند و در هر مقداردهی ساختار والد دوباره ایجاد می‌شود. اگر والد از @StateObject برای شیء استفاده کند، viewهای فرزند می‌توانند با خیال راحت از @ObservedObject استفاده کنند — شیء در کل سلسله‌مراتب یکتا خواهد بود.

@ObservedObject چگونه تغییرات را ردیابی می‌کند

مکانیزم ردیابی @ObservedObject بر اساس Combine و پروتکل ObservableObject است. هنگام مقداردهی، SwiftUI publisher objectWillChange را فراخوانی می‌کند — شیء باید قبل از تغییر ویژگی @Published سیگنال ارسال کند. Combine سیگنال را به گراف وابستگی SwiftUI منتقل می‌کند که تمام viewهای وابسته را به عنوان نیازمند به‌روزرسانی علامت‌گذاری می‌کند. این به صورت همزمان قبل از تغییر مقدار رخ می‌دهد.

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 ایجاد می‌کند و آن را به viewهای فرزند به عنوان @ObservedObject منتقل می‌کند. این یک انتقال سلسله‌مراتبی استاندارد داده است که در آن view ریشه چرخه عمر مدل را مدیریت می‌کند و تمام کامپوننت‌های تو در تو در تغییرات مشترک می‌شوند.

الگوی دوم — EnvironmentObject، نسخه سراسری @ObservedObject از طریق SwiftUI Environment. شیء در سطح صحنه یا view ریشه تزریق می‌شود و به طور خودکار برای تمام کامپوننت‌های فرزند بدون انتقال صریح از طریق مقداردهی‌کننده‌ها قابل دسترس است. در داخل view فرزند، @EnvironmentObject مشابه @ObservedObject کار می‌کند اما شیء را از محیط دریافت می‌کند.

الگوی سوم — ترکیب چند ObservableObject. در برنامه‌های پیچیده، view می‌تواند چندین شیء را مشاهده کند: @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("خوش آمدید، \\(user.name)")
            HStack {
                Circle()
                    .fill(network.isConnected ? Color.green : Color.red)
                    .frame(width: 10, height: 10)
            }
        }
    }
}

DashboardView UserViewModel و NetworkMonitor را مشاهده می‌کند. هر شیء مسئول حوزه داده خود است و به طور مستقل view را از تغییرات مطلع می‌کند. اگر شبکه قطع شود، NetworkMonitor isConnected را تغییر می‌دهد و SwiftUI DashboardView را دوباره ترسیم می‌کند و رنگ نشانگر را به‌روز می‌کند. ترکیب ObservableObject روش ترجیحی سازماندهی داده در برنامه‌های SwiftUI است.

@Published: ارتباط ObservableObject و SwiftUI

@Published یک Property Wrapper از Combine است که به طور خودکار به ویژگی داخل ObservableObject ناشر اضافه می‌کند. وقتی ویژگی @Published تغییر می‌کند، Combine از طریق publisher objectWillChange رویداد تولید می‌کند. SwiftUI هنگام استفاده از @ObservedObject یا @StateObject در این ناشر مشترک می‌شود و view را در هر مقدار جدید دوباره ترسیم می‌کند.

@Published از همه انواع از جمله اختیاری، مجموعه‌ها و ساختارهای سفارشی پشتیبانی می‌کند. با این حال، برای مجموعه‌ها (آرایه‌ها، دیکشنری‌ها) SwiftUI فقط جایگزینی مرجع را ردیابی می‌کند، نه تغییر محتوا را. برای تشخیص افزودن یا حذف عنصر، باید مجموعه را به طور کامل دوباره اختصاص دهید یا از ObservableObject با objectWillChange.send() دستی استفاده کنید.

نکته مهم: @Published فقط باید داخل کلاسی قرار گیرد که ObservableObject را پیاده‌سازی می‌کند. استفاده از @Published خارج از ObservableObject باعث خطای کامپایل می‌شود. همچنین @Published را نمی‌توان برای ویژگی‌های مقداردهی تنبل (lazy var) یا ویژگی‌های محاسبه‌شده (computed property) اعمال کرد.

خطاهای رایج با @ObservedObject

مهم‌ترین خطا — استفاده از @ObservedObject برای ایجاد شیء. اگر در view والد @ObservedObject var model = UserViewModel() بنویسید، در هر رندر یک نمونه جدید UserViewModel ایجاد می‌شود. داده‌ها از دست می‌روند و اشتراک‌های @Published دوباره ایجاد می‌شوند. همیشه از @StateObject برای ایجاد و از @ObservedObject فقط برای دریافت شیء آماده استفاده کنید.

خطای دوم — تغییر ویژگی‌های @Published خارج از نخ اصلی. ObservableObject از Combine استفاده می‌کند که نیاز به ارسال تغییرات در نخ اصلی (main actor) دارد. اگر @Published را در صف پس‌زمینه تغییر دهید، SwiftUI ممکن است view را در زمان نامناسبی دوباره ترسیم کند و باعث race conditions شود. برای به‌روزرسانی از DispatchQueue.main.async یا @MainActor استفاده کنید.

مشکل سوم — به‌روزرسانی‌های چرخه‌ای. اگر تغییر @Published عوارض جانبی ایجاد کند که دوباره @Published را تغییر دهد، یک حلقه بی‌نهایت ترسیم مجدد ایجاد می‌شود. راه‌حل: از پرچم‌های محافظ (isUpdating) استفاده کنید یا منطق را به ObservableObjectهای مختلف با مرزهای مسئولیت مشخص تقسیم کنید.

سوالات متداول

آیا @ObservedObject می‌تواند اختیاری باشد؟

بله، SwiftUI از @ObservedObject var model: UserViewModel? پشتیبانی می‌کند. با این حال، view تا زمانی که شیء nil باشد در تغییرات مشترک نخواهد شد. هنگام تخصیص مقدار، اشتراک به طور خودکار فعال می‌شود.

@ObservedObject چه تفاوتی با @EnvironmentObject دارد؟

@ObservedObject شیء را از طریق مقداردهی‌کننده دریافت می‌کند، @EnvironmentObject از طریق SwiftUI Environment. @EnvironmentObject نیاز به انتقال صریح از طریق سازنده‌ها ندارد، اما شیء باید در سطح بالایی سلسله‌مراتب تزریق شود.

چگونه به صورت دستی SwiftUI را از تغییر ObservableObject مطلع کنیم؟

قبل از تغییر ویژگی objectWillChange.send() را فراخوانی کنید. این زمانی مفید است که @Published مناسب نیست (مثلاً برای ویژگی‌های محاسبه‌شده یا عملیات مجموعه‌ها که باید قبل از تغییر گزارش شود).

چرا @ObservedObject view را هنگام تغییر داخل آرایه دوباره ترسیم نمی‌کند؟

@ObservedObject و @Published جایگزینی مرجع را ردیابی می‌کنند، نه تغییر محتوای مجموعه را. برای ترسیم مجدد باید آرایه را دوباره اختصاص دهید: items.append(newItem) → items = items یا قبل از تغییر از objectWillChange.send() استفاده کنید.

آیا می‌توان از @ObservedObject در ساختاری که View را پیاده‌سازی نمی‌کند استفاده کرد؟

خیر، @ObservedObject یک Property Wrapper SwiftUI است که فقط در داخل انواع پیاده‌کننده پروتکل View قابل دسترس است. برای ساختارهای معمولی مستقیماً از Combine با ObservableObjectPublisher استفاده کنید.

خلاصه

  • @ObservedObject — Property Wrapper برای مشاهده ObservableObject بدون مالکیت
  • @StateObject — شیء را ایجاد می‌کند، @ObservedObject — موجود را مشاهده می‌کند
  • @Published — ناشر خودکار برای ویژگی‌های ObservableObject
  • اشتراک — SwiftUI به طور خودکار اشتراک Combine را هنگام استفاده از @ObservedObject مدیریت می‌کند
  • ترکیب — view می‌تواند همزمان چندین ObservableObject را مشاهده کند
  • Main actor — ویژگی‌های @Published فقط در نخ اصلی باید تغییر کنند
  • EnvironmentObject — جایگزین @ObservedObject برای انتقال ضمنی از طریق محیط

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید