Delegate: mi ez, delegációs minta és iOS protokollok

Szerző: IT Sectr Megjelenés: 2026-02-17 Olvasási idő: 9 perc

Delegate — egy tervezési minta, amelyben egy objektum egy feladat végrehajtását egy másik objektumra delegálja. iOS-ben a minta Swift protokollokon és @protocol Objective-C-n keresztül valósul meg. A Delegation a Cocoa Touch egyik alapvető mintája, amelyet a UITableViewDelegate, UITextFieldDelegate és több száz más Apple API használ. Az Apple Developer Documentation (2025) szerint az UIKit rendszerosztályainak körülbelül 70%-a delegáltakat használ a viselkedés testreszabásához öröklés nélkül.

Fő pontok

  • Delegate — minta, amelyben az A objektum a feladat végrehajtását a B objektumra delegálja protokollon vagy interfészen keresztül
  • Swift protokoll meghatározza azon metódusok készletét, amelyeket a delegált megvalósíthat vagy köteles megvalósítani
  • Weak referencia a delegáltra kötelező a retain cycle és memóriaszivárgás megelőzéséhez
  • UITableViewDelegate — a legelterjedtebb példa delegáltra iOS-ben 20+ opcionális metódussal
  • Különbség az Observer-től: a delegált 1:1 kapcsolat, míg az értesítések 1:N elv szerint működnek

Mi a Delegate minta?

Delegate — egy viselkedéstervezési minta, amely lehetővé teszi egy objektum számára, hogy felelősségeinek egy részét egy másik objektumra ruházza. Az örökléstől eltérően, ahol a gyermekosztály felülírja a szülő metódusait, a delegált kompozíciót használ: a tulajdonos objektum tárol egy referenciát a delegáltra, és meghívja annak metódusait meghatározott pontokon.

A delegált meghatározza a protokollt — egy metóduskészletet, amelyet a delegált megvalósíthat. A metódusok kötelező (required) és opcionális (optional) kategóriákra oszlanak. Swift-ben a protokoll opcionális metódusait az @objc optional kulcsszó jelöli.

A delegált működési elve

Az A objektum (tulajdonos) tartalmazza a delegate tulajdonságot — egy weak referenciát a B objektumra (delegált). Amikor egy esemény történik, A ellenőrzi, hogy B implementálja-e a megfelelő protokollmetódust, és meghívja azt. A weak referencia kötelező: nélküle a delegált nem szabadítható fel a memóriából, mivel a tulajdonos erős referenciával tartja.

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)
        // aszinkron betöltés
    }
}

A DataLoader osztály meghatározza a LoaderDelegate protokollt, és meghívja a delegált metódusait a betöltési életciklus kulcsfontosságú pontjain. Az AnyObject garantálja, hogy a protokoll csak osztályok által implementálható — ez szükséges a weak referenciához.

Hogyan működik a Delegate Swift-ben?

A delegált megvalósítása Swift-ben három lépést foglal magában: a protokoll deklarálása, a weak delegate tulajdonság létrehozása a tulajdonosban, és a protokoll implementálása a delegált osztályban. Tekintsük meg egy egyéni UITextField példáján validációval.

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("Érvényesítés sikertelen: a bemenet túl rövid")
    }
}

A LoginViewController implementálja a ValidatorDelegate protokollt, és beállítja magát a textField delegáltjának. Minden szövegváltozáskor a ValidatedTextField meghívja a validate(_:)-t, és ha a validáció sikertelen — validatorDidFail(_:)-t. A Controller közvetítőként működik a View és a validációs logika között.

Delegate vs NotificationCenter vs Closure

A választás delegált, értesítések és closure-ök között a címzettek számától és a komponensek kapcsolódási fokától függ. Minden mechanizmus megoldja az objektumok közötti kommunikáció problémáját, de különböző kompromisszumokkal.

JellemzőDelegateNotificationCenterClosure
Kapcsolat típusa1:11:N1:1
KapcsolódásGyenge (protokollon keresztül)Nagyon gyenge (karakterlánc-kulcs)Közepes (kontextus rögzítése)
TípusbiztonságTeljesNincs (Any?)Teljes
Retain cycle kockázatNem (weak)NemIgen (self rögzítése)
Mikor alkalmazzukÖsszetett callback-ek több metódussalEsemények, amelyek sokakat érdekelnekEgyszerű closure-ök 1-2 callback-kel

Delegate optimális, amikor egy sor kapcsolódó eseményt kell továbbítani egy címzettnek. NotificationCenter jobb broadcast értesítésekhez. Closure — egyszerű aszinkron műveletekhez, mint a completion handler az URLSession-ben.

Delegate megvalósítása Objective-C-ben

Objective-C a @protocol és @optional használatával deklarálja a delegáltakat. A Swift-től eltérően a protokoll összes metódusa alapértelmezés szerint opcionális. A legfontosabb különbség — a respondsToSelector: meghívása, mielőtt üzenetet küldene a delegáltnak, mivel a metódus lehet, hogy nincs implementálva.

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];
    }
    // aszinkron képbetöltés
}
@end

A legfontosabb különbség Objective-C-ben: egy opcionális metódus meghívása előtt ellenőrizni kell a respondsToSelector:-t. Swift-ben a protokoll opcionális metódusai kiküszöbölik ezt az ellenőrzést — az optional chaining (?.) automatikusan kezeli az implementáció hiányának esetét.

Tipikus hibák a delegáltakkal való munka során

A delegáltak használatának hibái memóriaszivárgáshoz, az alkalmazás összeomlásához és nem nyilvánvaló hibákhoz vezetnek. Tekintsük az öt leggyakoribb problémát.

Erős referencia a delegáltra

Retain cycle — a leggyakoribb hiba. Ha a delegate tulajdonság strong-ként van deklarálva, és a delegált pedig a tulajdonos objektum tulajdonosa, egy megtartási ciklus jön létre. Mindkét objektum soha nem szabadul fel a memóriából. Megoldás: mindig deklarálja a delegáltat weak var-ként Swift-ben vagy @property (weak)-ként Objective-C-ben.

A delegált nem nullázódott a dealloc után

Ha a tulajdonos objektum túléli a delegáltat, és a referencia megmarad, a delegált metódusának meghívása EXC_BAD_ACCESS-t okoz. A weak referencia automatikusan megoldja ezt a problémát: a delegált felszabadítása után a tulajdonság nil lesz. Többszálú forgatókönyvekben azonban érdemes a delegáltat a fő szálon is ellenőrizni.

Túlzott metódusszám a protokollban

A 20+ metódussal rendelkező protokoll megsérti az interfész elkülönítés elvét (ISP). Az UITableViewDelegate körülbelül 30 opcionális metódust tartalmaz — ez történelmi kivétel. Saját protokolljaiban jobb a felelősséget több kis protokollra osztani, mindegyiknek saját szereppel.

Delegate példák iOS rendszer API-kban

Az Apple rendszer API-i aktívan használják a Delegate mintát. Tekintsünk három kulcsfontosságú példát az UIKit-ből, amelyek minden iOS alkalmazásban megtalálhatók.

APIProtokollKulcs metódusok
UITableViewUITableViewDelegatedidSelectRowAt, heightForRowAt, willDisplay
UITextFieldUITextFieldDelegateshouldChangeCharactersIn, didBeginEditing, shouldReturn
URLSessionURLSessionDelegatedidReceiveChallenge, didCompleteWithError, didBecomeInvalidWithError

Ezen protokollok mindegyike a viselkedés különböző aspektusait valósítja meg: UITableViewDelegate kezeli a megjelenést és az érintésre adott reakciót, UITextFieldDelegate vezérli a szövegbevitelt, URLSessionDelegate feldolgozza a hálózati eseményeket. Ez mutatja a minta rugalmasságát: a delegált bármilyen felelősségi területhez igazítható.

Gyakran Ismételt Kérdések

Mi a különbség a delegate és a dataSource között iOS-ben?

Delegate kezeli a viselkedést és a megjelenést (cella magassága, érintésre adott reakció). DataSource biztosítja az adatokat (sorok száma, cellák tartalma). Az UITableViewDelegate és UITableViewDataSource — két külön protokoll, amelyek megosztják a felelősséget a megjelenítés és az adatok között.

Miért van a delegate weak-ként deklarálva?

A weak referencia megakadályozza a retain cycle-t. A tulajdonos (pl. UITableView) csak weak-ként tartja a referenciát a delegáltra. Ha a delegált (UIViewController) birtokolja a táblázatot, egy erős referencia a delegáltra ciklust hozna létre: ViewController → UITableView → Delegate (ViewController). A Weak megszakítja ezt a ciklust.

Használható-e delegate a SwiftUI-ban?

A SwiftUI-ban a Delegate minta ritkábban használt — a @Binding, @State és closure-ök helyettesítik. Azonban a delegate továbbra is használatos az UIKit integrációhoz UIViewRepresentable-en keresztül. Például az MKMapViewDelegate és WKUIDelegate továbbra is relevánsak az UIKit komponensek SwiftUI-ba csomagolásakor.

Mi az @objc optional a Swift protokollokban?

@objc optional lehetővé teszi opcionális metódusok deklarálását egy Swift protokollban. Ez egy kompatibilitási mechanizmus az Objective-C runtime-tal. @objc nélkül a Swift protokoll összes metódusa alapértelmezés szerint kötelező. Az Optional az UIKit protokollokban használatos, ahol a delegált csak a szükséges metódusokat implementálhatja.

Hány delegáltja lehet egy objektumnak?

Egy objektumnak csak egy delegáltja lehet minden delegate tulajdonsághoz. Ha több objektumot kell értesíteni, használjon multicast delegate-t, delegáltak tömbjét vagy NotificationCenter-t. A Delegate minta alapvetően 1:1 kapcsolatként lett tervezve.

Összefoglaló

  • Delegate — viselkedéstervezési minta, amely egy feladat végrehajtását az egyik objektumtól a másikhoz protokollon keresztül továbbítja
  • Swift protokoll deklarálja a metódusok készletét; az opcionális metódusok @objc optional-lal vannak jelölve, a kötelezők mindig implementálva vannak
  • Weak referencia a delegáltra kötelező a retain cycle és memóriaszivárgás megelőzéséhez
  • UITableViewDelegate — a legismertebb példa; metódusai kezelik a cellák magasságát, kiválasztását és megjelenítését
  • Delegate különbözik a NotificationCenter-től az 1:1 versus 1:N kapcsolatban és a teljes típusbiztonságban
  • Objective-C megköveteli a respondsToSelector: ellenőrzését az opcionális metódusokhoz, Swift ezt automatikusan kezeli
  • Javaslat: használjon delegate-t összetett callback-ekhez több kapcsolódó metódussal és closure-t egyszerű lezárásokhoz

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is