Delegate: چیست، الگوی تفویض و پروتکل‌های iOS

نویسنده: IT Sectr منتشر شده: 2026-02-17 زمان مطالعه: 9 دقیقه

Delegate — یک الگوی طراحی است که در آن یک شیء اجرای وظیفه را به شیء دیگر تفویض می‌کند. در iOS این الگو از طریق پروتکل‌های Swift و @protocol Objective-C پیاده‌سازی می‌شود. Delegation یکی از الگوهای بنیادین Cocoa Touch است که در UITableViewDelegate، UITextFieldDelegate و صدها API دیگر Apple استفاده می‌شود. طبق Apple Developer Documentation (2025)، حدود 70٪ از کلاس‌های سیستمی UIKit از تفویض‌کنندگان برای سفارشی‌سازی رفتار بدون وراثت استفاده می‌کنند.

نکات اصلی

  • Delegate — الگویی که در آن شیء A اجرای وظیفه را به شیء B از طریق پروتکل یا رابط تفویض می‌کند
  • پروتکل Swift مجموعه‌ای از متدها را تعریف می‌کند که تفویض‌کننده می‌تواند یا باید پیاده‌سازی کند
  • مرجع Weak به تفویض‌کننده برای جلوگیری از retain cycle و نشت حافظه الزامی است
  • UITableViewDelegate — رایج‌ترین مثال تفویض‌کننده در iOS با ۲۰+ متد اختیاری
  • تفاوت با Observer: تفویض‌کننده رابطه ۱:۱ است، در حالی که اعلان‌ها بر اساس اصل ۱:N کار می‌کنند

الگوی Delegate چیست؟

Delegate — یک الگوی طراحی رفتاری است که به یک شیء اجازه می‌دهد بخشی از وظایف خود را به شیء دیگر منتقل کند. بر خلاف وراثت، حيث کلاس فرزند متدهای والد را بازنویسی می‌کند، تفویض‌کننده از ترکیب استفاده می‌کند: شیء-مالک یک مرجع به تفویض‌کننده ذخیره می‌کند و متدهای آن را در نقاط مشخصی فراخوانی می‌کند.

تفویض‌کننده پروتکل را تعریف می‌کند — مجموعه‌ای از متدها که تفویض‌کننده می‌تواند پیاده‌سازی کند. متدها به اجباری (required) و اختیاری (optional) تقسیم می‌شوند. در Swift متدهای اختیاری پروتکل با کلمه کلیدی @objc optional مشخص می‌شوند.

اصل کار تفویض‌کننده

شیء A (مالک) دارای ویژگی delegate است — یک مرجع weak به شیء B (تفویض‌کننده). وقتی رویدادی رخ می‌دهد، A بررسی می‌کند که آیا B متد مربوط به پروتکل را پیاده‌سازی می‌کند و آن را فراخوانی می‌کند. مرجع weak الزامی است: بدون آن، تفویض‌کننده نمی‌تواند از حافظه آزاد شود، زیرا مالک آن را با یک مرجع قوی نگه می‌دارد.

Swift
protocol LoaderDelegate: AnyObject {
    func loaderDidStart(_ loader: DataLoader)
    func loader(_ loader: DataLoader, didLoad data: Data)
    func loader(_ loader: DataLoader, didFailWith error: Error)
}

class DataLoader {
    weak var delegate: LoaderDelegate?
    
    func start() {
        delegate?.loaderDidStart(self)
        // بارگیری ناهمزمان
    }
}

کلاس DataLoader پروتکل LoaderDelegate را تعریف می‌کند و متدهای تفویض‌کننده را در نقاط کلیدی چرخه عمر بارگیری فراخوانی می‌کند. AnyObject تضمین می‌کند که پروتکل فقط توسط کلاس‌ها قابل پیاده‌سازی است — این برای مرجع weak ضروری است.

Delegate در Swift چگونه کار می‌کند؟

پیاده‌سازی تفویض‌کننده در Swift شامل سه مرحله است: اعلام پروتکل، ایجاد ویژگی weak delegate در مالک و پیاده‌سازی پروتکل در کلاس-تفویض‌کننده. بیایید با مثال یک UITextField سفارشی با اعتبارسنجی بررسی کنیم.

Swift
protocol ValidatorDelegate: AnyObject {
    func validate(_ input: String) -> Bool
    func validatorDidFail(_ input: String)
}

class ValidatedTextField: UITextField {
    weak var validator: ValidatorDelegate?
    
    override func textDidChange() {
        guard let text = self.text else { return }
        if validator?.validate(text) == false {
            validator?.validatorDidFail(text)
            self.layer.borderColor = UIColor.red.cgColor
        }
    }
}

class LoginViewController: UIViewController, ValidatorDelegate {
    let textField = ValidatedTextField()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        textField.validator = self
    }
    
    func validate(_ input: String) -> Bool {
        return input.count >= 6
    }
    
    func validatorDidFail(_ input: String) {
        print("اعتبارسنجی ناموفق: ورودی بسیار کوتاه است")
    }
}

LoginViewController پروتکل ValidatorDelegate را پیاده‌سازی می‌کند و خود را به عنوان تفویض‌کننده textField تعیین می‌کند. با هر تغییر متن، ValidatedTextField متد validate(_:) را فراخوانی می‌کند و اگر اعتبارسنجی ناموفق باشد — validatorDidFail(_:). Controller به عنوان واسط بین View و منطق اعتبارسنجی عمل می‌کند.

Delegate در مقابل NotificationCenter در مقابل Closure

انتخاب بین تفویض‌کننده، اعلان‌ها و بسته‌ها به تعداد دریافت‌کنندگان و درجه وابستگی مؤلفه‌ها بستگی دارد. هر مکانیزم مشکل ارتباط بین اشیاء را حل می‌کند، اما با مصالحه‌های متفاوت.

ویژگیDelegateNotificationCenterClosure
نوع ارتباط۱:۱۱:N۱:۱
وابستگیضعیف (از طریق پروتکل)بسیار ضعیف (رشته-کلید)متوسط (گرفتن زمینه)
ایمنی نوعکاملندارد (Any?)کامل
ریسک retain cycleخیر (weak)خیربله (گرفتن self)
زمان استفادهفراخوانی‌های پیچیده با چندین متدرویدادهایی که بسیاری را علاقه‌مند می‌کندبسته‌های ساده با ۱-۲ فراخوانی

Delegate بهینه است وقتی باید یک سری رویدادهای مرتبط به یک دریافت‌کننده ارسال شود. NotificationCenter برای اعلان‌های broadcast بهتر است. Closure — برای عملیات‌های ناهمزمان ساده، مانند completion handler در URLSession.

پیاده‌سازی Delegate در Objective-C

Objective-C از @protocol و @optional برای اعلام تفویض‌کنندگان استفاده می‌کند. بر خلاف Swift، تمام متدهای پروتکل به طور پیش‌فرض اختیاری هستند. تفاوت کلیدی — فراخوانی respondsToSelector: قبل از ارسال پیام به تفویض‌کننده، زیرا ممکن است متد پیاده‌سازی نشده باشد.

Objective-C
@protocol ImageCacheDelegate 
@optional
- (void)cacheDidStartDownload: (ImageCache *)cache;
- (void)cache: (ImageCache *)cache didCacheImage: (UIImage *)image;
@required
- (void)cache: (ImageCache *)cache didFailWithError: (NSError *)error;
@end

@interface ImageCache : NSObject
@property (nonatomic, weak) id<ImageCacheDelegate> delegate;
- (void)downloadImageAtURL: (NSURL *)url;
@end

@implementation ImageCache
- (void)downloadImageAtURL: (NSURL *)url {
    if ([self.delegate respondsToSelector:@selector(cacheDidStartDownload:)]) {
        [self.delegate cacheDidStartDownload:self];
    }
    // بارگیری ناهمزمان تصویر
}
@end

تفاوت کلیدی در Objective-C: قبل از فراخوانی متد اختیاری، بررسی respondsToSelector: ضروری است. در Swift متدهای اختیاری پروتکل این بررسی را حذف می‌کنند — optional chaining (?.) به طور خودکار حالت عدم پیاده‌سازی را مدیریت می‌کند.

خطاهای رایج هنگام کار با تفویض‌کنندگان

خطاهای استفاده از تفویض‌کنندگان منجر به نشت حافظه، crashes برنامه و باگ‌های غیربدیهی می‌شود. بیایید پنج مشکل رایج را بررسی کنیم.

مرجع قوی به تفویض‌کننده

Retain cycle — رایج‌ترین خطا. اگر ویژگی delegate به عنوان strong اعلام شود و تفویض‌کننده نیز به نوبه خود مالک شیء-مالک باشد، یک چرخه نگهداری تشکیل می‌شود. هر دو شیء هرگز از حافظه آزاد نخواهند شد. راه‌حل: همیشه تفویض‌کننده را به عنوان weak var در Swift یا @property (weak) در Objective-C اعلام کنید.

تفویض‌کننده پس از dealloc صفر نشده است

اگر شیء-مالک از تفویض‌کننده بیشتر عمر کند و مرجع باقی بماند، فراخوانی متد تفویض‌کننده منجر به EXC_BAD_ACCESS می‌شود. مرجع weak این مشکل را به طور خودکار حل می‌کند: پس از آزاد شدن تفویض‌کننده، ویژگی nil می‌شود. با این حال، در سناریوهای چندنخی بهتر است تفویض‌کننده را در نخ اصلی نیز بررسی کنید.

تعداد بیش از حد متدها در پروتکل

پروتکلی با بیش از ۲۰ متد اصل جداسازی رابط‌ها (ISP) را نقض می‌کند. UITableViewDelegate حدود ۳۰ متد اختیاری دارد — این یک استثنای تاریخی است. در پروتکل‌های خود بهتر است مسئولیت را به چند پروتکل کوچک تقسیم کنید، هر کدام با نقش خود.

مثال‌های Delegate در API‌های سیستمی iOS

API‌های سیستمی Apple به طور فعال از الگوی Delegate استفاده می‌کنند. بیایید سه مثال کلیدی از UIKit را بررسی کنیم که در هر برنامه iOS یافت می‌شوند.

APIپروتکلمتدهای کلیدی
UITableViewUITableViewDelegatedidSelectRowAt, heightForRowAt, willDisplay
UITextFieldUITextFieldDelegateshouldChangeCharactersIn, didBeginEditing, shouldReturn
URLSessionURLSessionDelegatedidReceiveChallenge, didCompleteWithError, didBecomeInvalidWithError

هر یک از این پروتکل‌ها جنبه‌های مختلف رفتار را پیاده‌سازی می‌کنند: UITableViewDelegate ظاهر و واکنش به لمس را مدیریت می‌کند، UITextFieldDelegate ورود متن را کنترل می‌کند، URLSessionDelegate رویدادهای شبکه را پردازش می‌کند. این انعطاف‌پذیری الگو را نشان می‌دهد: تفویض‌کننده می‌تواند با هر حوزه مسئولیتی سازگار شود.

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

تفاوت بین delegate و dataSource در iOS چیست؟

Delegate رفتار و ظاهر را مدیریت می‌کند (ارتفاع سلول، واکنش به لمس). DataSource داده‌ها را فراهم می‌کند (تعداد ردیف‌ها، محتوای سلول‌ها). در UITableViewDelegate و UITableViewDataSource — این دو پروتکل جداگانه هستند که مسئولیت ارائه و داده را تقسیم می‌کنند.

چرا delegate به عنوان weak اعلام می‌شود؟

مرجع weak از retain cycle جلوگیری می‌کند. مالک (مثلاً UITableView) مرجع را به تفویض‌کننده فقط به صورت weak نگه می‌دارد. اگر تفویض‌کننده (UIViewController) مالک جدول باشد، مرجع قوی به تفویض‌کننده یک چرخه ایجاد می‌کند: ViewController → UITableView → Delegate (ViewController). Weak این چرخه را می‌شکند.

آیا می‌توان از delegate در SwiftUI استفاده کرد؟

در SwiftUI الگوی Delegate کمتر استفاده می‌شود — @Binding، @State و بسته‌ها جایگزین آن می‌شوند. با این حال، delegate همچنان برای یکپارچه‌سازی UIKit از طریق UIViewRepresentable استفاده می‌شود. برای مثال، MKMapViewDelegate و WKUIDelegate هنگام بسته‌بندی مؤلفه‌های UIKit در SwiftUI همچنان مرتبط هستند.

@objc optional در پروتکل‌های Swift چیست؟

@objc optional امکان اعلام متدهای اختیاری در پروتکل Swift را فراهم می‌کند. این یک مکانیسم سازگاری با Objective-C runtime است. بدون @objc همه متدهای پروتکل Swift به طور پیش‌فرض اجباری هستند. Optional در پروتکل‌های UIKit استفاده می‌شود، جایی که تفویض‌کننده می‌تواند فقط متدهای مورد نیاز خود را پیاده‌سازی کند.

یک شیء چند تفویض‌کننده می‌تواند داشته باشد؟

یک شیء می‌تواند فقط یک تفویض‌کننده برای هر ویژگی delegate داشته باشد. اگر نیاز به اطلاع‌رسانی به چندین شیء دارید، از multicast delegate، آرایه‌ای از تفویض‌کنندگان یا NotificationCenter استفاده کنید. الگوی Delegate اساساً به عنوان یک رابطه ۱:۱ طراحی شده است.

خلاصه

  • Delegate — یک الگوی طراحی رفتاری است که اجرای وظیفه را از یک شیء به شیء دیگر از طریق پروتکل منتقل می‌کند
  • پروتکل Swift مجموعه‌ای از متدها را اعلام می‌کند؛ متدهای اختیاری با @objc optional مشخص می‌شوند، متدهای اجباری همیشه پیاده‌سازی می‌شوند
  • مرجع weak به تفویض‌کننده برای جلوگیری از retain cycle و نشت حافظه الزامی است
  • UITableViewDelegate — معروف‌ترین مثال؛ متدهای آن ارتفاع، انتخاب و نمایش سلول‌ها را مدیریت می‌کنند
  • Delegate با NotificationCenter از نظر رابطه ۱:۱ در مقابل ۱:N و ایمنی کامل نوع تفاوت دارد
  • Objective-C برای متدهای اختیاری نیاز به بررسی respondsToSelector: دارد، Swift این را به طور خودکار مدیریت می‌کند
  • توصیه: از delegate برای فراخوانی‌های پیچیده با چندین متد مرتبط و از closure برای بسته‌های ساده استفاده کنید

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

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

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

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