OperationQueue یک صف وظایف سطح بالا در iOS و macOS است که بر روی Grand Central Dispatch ساخته شده است. به گفته Apple Developer Documentation, 2026، OperationQueue نمونههای Operation — اشیایی که یک واحد کار را کپسوله میکنند — مدیریت میکند. برخلاف DispatchQueue، OperationQueue از وابستگیهای بین عملیاتها، اولویتها، مشاهده KVO و لغو وظایف در حال اجرا پشتیبانی میکند. OperationQueue به طور خودکار استخر رشتهها را مدیریت کرده و عملیاتها را بر اساس منابع موجود سیستم توزیع میکند.
نکات اصلی
OperationQueue کلاسی از فریمورک Foundation است که اجرای اشیاء Operation را مدیریت میکند. برخلاف DispatchQueue، OperationQueue نیاز به مشخص کردن صریح حالت serial یا concurrent ندارد — تعداد عملیاتهای همزمان توسط ویژگی maxConcurrentOperationCount تنظیم میشود. مقدار 1 صف را به sequential تبدیل میکند، هر مقدار دیگر آن را به concurrent تبدیل میکند.
Operation یک کلاس انتزاعی است که یک واحد کار را نشان میدهد. هر عملیات دارای وضعیت است: ready، executing، finished یا cancelled. وضعیتها با KVO (Key-Value Observing) سازگار هستند که امکان واکنش به تغییرات — بهروزرسانی UI هنگام اتمام عملیات — را فراهم میکند. Operation به طور خودکار پرچمهای isExecuting و isFinished را مدیریت میکند.
به گفته Apple (2026)، OperationQueue در زیرساخت خود از GCD استفاده میکند، اما قابلیتهایی را اضافه میکند که در DispatchQueue در دسترس نیستند: وابستگیها، اولویتها و لغو عملیاتها. اگر برنامه به حالت پسزمینه برود، OperationQueue اجرا را متوقف میکند و هنگام بازگشت از سر میگیرد. OperationQueue همچنین به طور خودکار تعداد هستههای پردازنده را در نظر گرفته و تعداد بهینه رشتهها را انتخاب میکند.
هر عملیات چهار وضعیت را طی میکند: pending (در انتظار)، ready (آماده اجرا)، executing (در حال اجرا) و finished (تکمیل شده). وضعیت cancelled میتواند در هر مرحله قبل از اتمام رخ دهد. انتقال بین وضعیتها از طریق KVO ردیابی میشود — این اساس بهروزرسانی واکنشگرای UI است. OperationQueue به طور خودکار عملیاتهای تکمیل شده را از صف حذف میکند و به عملیاتهای وابسته اطلاع میدهد که پیشنیازشان برآورده شده است و اجرای آنها را آغاز میکند.
Operation یک کلاس انتزاعی است که نیاز به بازنویسی متد main() یا start() دارد. در متد main() کد وظیفه قرار میگیرد و وضعیت isExecuting و isFinished به طور خودکار مدیریت میشود. برای عملیاتهای ناهمزمان نیاز به بازنویسی start() و مدیریت دستی پرچمهای وضعیت است.
BlockOperation پیادهسازی مشخصی از Operation است که یک یا چند بلوک کد را اجرا میکند. BlockOperation زمانی concurrent میشود که چندین بلوک از طریق addExecutionBlock() به آن اضافه شود. عملیات تنها پس از اجرای تمام بلوکهای اضافه شده تکمیل میشود. BlockOperation جایگزین مناسبی برای وظایف ساده بدون نیاز به وراثت است.
| ویژگی | Operation | BlockOperation |
|---|---|---|
| نوع کلاس | انتزاعی | مشخص |
| وراثت | الزامی | غیرضروری |
| ناهمزمانی | مدیریت دستی KVO | خودکار |
| بلوکهای کد | یکی در main() | یک یا چند |
| کاربرد | وظایف پیچیده با وضعیت | وظایف ساده یکباره |
| مناسب برای | وابستگیها، لغو، پیشرفت | بلوکهای سریع، completion |
| حافظه | بیشتر به دلیل KVO و وضعیت | حداقل، سبک |
برای ایجاد یک عملیات سفارشی از Operation ارثبری کنید و main() را بازنویسی کنید. در داخل، قبل از عملیاتهای پرهزینه، پرچم isCancelled را بررسی کنید تا لغو سریع تضمین شود. این برای دانلود فایلهای بزرگ یا پردازش دستهای دادهها حیاتی است. انتخاب بین Operation و BlockOperation به پیچیدگی وظیفه بستگی دارد: برای اقدامات ساده یکباره BlockOperation کافی است، برای منطق قابل استفاده مجدد با وضعیت — ارثبری از Operation.
وابستگیها مزیت کلیدی OperationQueue نسبت به DispatchQueue هستند. متد addDependency(_:) مشخص میکند که عملیات B تنها پس از اتمام عملیات A اجرا شود. وابستگیها یک directed acyclic graph (DAG) تشکیل میدهند: هنگام اضافه شدن وابستگی چرخهای، صف آن را نادیده میگیرد و عملیاتها اجرا نمیشوند.
اولویت عملیات با ویژگی queuePriority با مقادیر .veryLow، .low، .normal، .high، .veryHigh تنظیم میشود. اولویت بر ترتیب شروع در میان عملیاتهای ready تأثیر میگذارد، اما وابستگیها را لغو نمیکند. OperationQueue ابتدا وابستگیها، سپس اولویت را در میان عملیاتهای موجود در نظر میگیرد.
سناریوی معمول — بارگیری دادههای پروفایل: ابتدا کاربر را بارگیری میکنیم، سپس بر اساس id او دوستان و پستها را بارگیری میکنیم. تنظیم وابستگی بین بارگیری کاربر و بارگیری دوستان ترتیب صحیح را بدون completion handler تو در تو تضمین میکند.
ویژگی maxConcurrentOperationCount تعداد عملیاتهای همزمان اجرا را محدود میکند. مقدار 1 یک صف sequential ایجاد میکند، مقدار پیشفرض (NSOperationQueueDefaultMaxConcurrentOperationCount) — بهینه سیستمی، وابسته به بار فعلی دستگاه است. تنظیم صحیح این پارامتر از مصرف بیش از حد منابع جلوگیری میکند: برای بارگیری تصاویر 4-6 عملیات concurrent کافی است، برای وظایف CPU-intensive — تعداد هستههای پردازنده.
انتخاب بین OperationQueue و DispatchQueue به پیچیدگی وظیفه بستگی دارد. DispatchQueue ابزاری سبک برای فراخوانیهای async ساده است. OperationQueue راهحل سنگینتری برای سناریوهای پیچیده با وظایف متعدد به هم مرتبط است. Apple توصیه میکند با DispatchQueue شروع کنید و فقط در صورت نیاز به وابستگیها یا لغو به OperationQueue بروید. برای اکثر پروژههای iOS ترکیب هر دو ابزار تعادل بهینهای از کارایی و انعطافپذیری ارائه میدهد.
به گفته Ray Wenderlich (2025)، در پروژههای بزرگ iOS از OperationQueue برای بارگیری محتوا با پیشرفت و لغو استفاده میشود و از DispatchQueue برای سایر عملیاتهای async. نسبت تقریباً 20 به 80 به نفع DispatchQueue است.
سه مثال را بررسی میکنیم: BlockOperation ساده، Operation سفارشی با وابستگیها و عملیات قابل لغو برای بارگیری دادهها.
سادهترین حالت — اجرای بلوک در OperationQueue و پردازش نتیجه از طریق completionBlock. هر Operation دارای ویژگی داخلی completionBlock است که پس از اتمام main() فراخوانی میشود.
let queue = OperationQueue()
let operation = BlockOperation()
operation.addExecutionBlock {
let data = NetworkService.fetchData()
OperationQueue.main.addOperation {
self.updateUI(data)
}
}
queue.addOperation(operation)
وابستگی تضمین میکند که parseOperation تنها پس از اتمام downloadOperation اجرا شود. این نیاز به callback تو در تو را از بین میبرد.
let download = BlockOperation { self.downloadJSON() }
let parse = BlockOperation { self.parseJSON() }
parse.addDependency(download)
let queue = OperationQueue()
queue.addOperations([download, parse], waitUntilFinished: false)
main() را با بررسی دورهای isCancelled بازنویسی کنید. این امکان توقف فوری عملیات را هنگام لغو، بدون انتظار برای اتمام عملیات پرهزینه فراهم میکند.
class ImageLoadOperation: Operation {
override func main() {
guard !self.isCancelled else { return }
let image = self.downloadImage()
guard !self.isCancelled else { return }
OperationQueue.main.addOperation { self.display(image) }
}
}
لغو عملیات پرچم isCancelled را روی true قرار میدهد، اما متد main() را که از قبل شروع شده متوقف نمیکند. کد داخل main() باید به طور مستقل isCancelled را بررسی کرده و در صورت لزوم پایان یابد. این تصمیم معماری Apple است — به توسعهدهنده اجازه میدهد در زمان لغو منابع را به درستی آزاد کند.
مشاهده KVO بر روی ویژگیهای isFinished و isExecuting امکان واکنش به اتمام عملیاتها بدون callback صریح را فراهم میکند. OperationQueue به طور خودکار عملیاتهای تکمیل شده را از صف حذف میکند، اما آنها تا زمانی که ارجاعات قوی به آنها وجود دارد در حافظه باقی میمانند. KVO اساس ادغام OperationQueue با فریمورکهای واکنشگرا مانند RxSwift یا Combine است.
اشتراک در isCancelled از طریق KVO امکان بهروزرسانی UI را هنگام لغو عملیات فراهم میکند — مثلاً نمایش placeholder به جای بارگیری لغو شده. ویژگی isCancelled سازگار با KVO است که آن را برای pipeline واکنشگرا مناسب میکند.
عملیاتها را در تعداد زیاد ایجاد نکنید — هر Operation یک شیء جداگانه در حافظه است. اگر وظیفه کوتاه است و نیازی به وابستگی ندارد، مستقیماً از DispatchQueue استفاده کنید. OperationQueue فقط برای سناریوهای پیچیده با وابستگیهای آشکار، لغو و نظارت بر پیشرفت توجیهپذیر است.
isCancelled را قبل از عملیاتهای پرهزینه بررسی کنید در داخل متد main(). در موارد دانلود فایل یا پردازش تصاویر، بررسی پس از هر مرحله مهم پاسخ سریع به لغو را تضمین میکند. از if isCancelled { return } در ابتدای main() و پس از هر عملیات بزرگ استفاده کنید.
completionBlock را به درستی مدیریت کنید. ویژگی completionBlock عملیات پس از اتمام main() فراخوانی میشود، حتی اگر عملیات لغو شده باشد. isCancelled را در داخل completionBlock بررسی کنید تا UI را با دادههای اشتباه بهروزرسانی نکنید. OperationQueue.main — صف thread-safe برای عملیات UI، مشابه DispatchQueue.main.
از وابستگیهای چرخهای خودداری کنید — آنها باعث میشوند هیچیک از عملیاتهای موجود در چرخه هرگز اجرا نشوند. OperationQueue چرخهها را به طور خودکار تشخیص نمیدهد: اگر A به B و B به A وابسته باشد، هر دو برای همیشه در وضعیت ready باقی میمانند. گراف وابستگی را از قبل برنامهریزی کنید.
سوالات متداول
OperationQueue بر روی GCD ساخته شده و وابستگیها، اولویتها، KVO و لغو عملیاتها را اضافه میکند. DispatchQueue ابزار سبکتری برای وظایف async ساده بدون این قابلیتها است.
ویژگی maxConcurrentOperationCount را روی 1 تنظیم کنید. این OperationQueue را با حفظ تمام مزایا — وابستگیها، اولویتها و لغو — به صف sequential تبدیل میکند.
متد cancel() پرچم isCancelled را تنظیم میکند، اما متد main() در حال اجرا را متوقف نمیکند. کد عملیات باید خود isCancelled را بررسی کرده و پایان یابد. لغو فقط برای عملیاتهای pending و ready کار میکند.
زمانی که مدیریت وضعیت، ناهمزمانی یا استفاده مجدد از منطق مورد نیاز است، باید از Operation ارثبری کرد. BlockOperation برای وظایف ساده یکباره بدون وراثت مناسب است.
خیر، مگر اینکه متد waitUntilFinished با پارامتر true در رشته اصلی فراخوانی شود. عملیاتها به طور پیشفرض در رشتههای پسزمینه اجرا میشوند و نتیجه از طریق OperationQueue.main بازگردانده میشود.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید