Delegate: vad är det, delegeringsmönster och iOS-protokoll

Författare: IT Sectr Publicerad: 2026-02-17 Lästid: 9 min

Delegate — är ett designmönster där ett objekt delegerar utförandet av en uppgift till ett annat objekt. I iOS implementeras mönstret via Swift-protokoll och @protocol Objective-C. Delegation är ett av de fundamentala mönstren i Cocoa Touch, som används i UITableViewDelegate, UITextFieldDelegate och hundratals andra Apple API:er. Enligt Apple Developer Documentation (2025) använder cirka 70% av systemklasserna i UIKit delegater för att anpassa beteende utan arv.

Huvudpunkter

  • Delegate — mönster där objekt A delegerar utförandet av en uppgift till objekt B via ett protokoll eller gränssnitt
  • Swift-protokoll definierar en uppsättning metoder som delegaten kan eller måste implementera
  • Weak-referens till delegaten är obligatorisk för att förhindra retain cycle och minnesläckor
  • UITableViewDelegate — det vanligaste exemplet på delegat i iOS med 20+ valfria metoder
  • Skillnad från Observer: delegat är en 1:1-relation, medan notifikationer fungerar enligt 1:N-principen

Vad är Delegate-mönstret?

Delegate — är ett beteendedesignmönster som tillåter ett objekt att överföra en del av sina ansvarsområden till ett annat objekt. Till skillnad från arv, där underklassen åsidosätter förälderns metoder, använder delegaten komposition: ägarobjektet lagrar en referens till delegaten och anropar dess metoder vid specifika punkter.

Delegaten definierar ett protokoll — en uppsättning metoder som delegaten kan implementera. Metoderna delas in i obligatoriska (required) och valfria (optional). I Swift markeras protokollets valfria metoder med nyckelordet @objc optional.

Delegatens funktionsprincip

Objekt A (ägaren) innehåller egenskapen delegate — en weak-referens till objekt B (delegaten). När en händelse inträffar kontrollerar A om B implementerar motsvarande protokollmetod och anropar den. Weak-referens är obligatorisk: utan den kan delegaten inte frigöras från minnet, eftersom ägaren håller den med en stark referens.

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)
        // asynkron laddning
    }
}

Klassen DataLoader definierar protokollet LoaderDelegate och anropar delegatens metoder vid nyckelpunkter i laddningslivscykeln. AnyObject garanterar att protokollet endast kan implementeras av klasser — detta är nödvändigt för weak-referensen.

Hur fungerar Delegate i Swift?

Implementering av delegaten i Swift omfattar tre steg: deklarera protokollet, skapa weak delegate-egenskapen i ägaren och implementera protokollet i delegatklassen. Låt oss titta på exemplet med en anpassad UITextField med validering.

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("Validering misslyckades: inmatningen är för kort")
    }
}

LoginViewController implementerar protokollet ValidatorDelegate och sätter sig själv som delegat för textField. Vid varje textändring anropar ValidatedTextField validate(_:), och om valideringen misslyckas — validatorDidFail(_:). Controller fungerar som medlare mellan View och valideringslogiken.

Delegate vs NotificationCenter vs Closure

Valet mellan delegat, notifikationer och closures beror på antalet mottagare och graden av koppling mellan komponenter. Varje mekanism löser problemet med kommunikation mellan objekt, men med olika avvägningar.

EgenskapDelegateNotificationCenterClosure
Typ av anslutning1:11:N1:1
KopplingSvag (via protokoll)Mycket svag (strängnyckel)Medel (fånga kontext)
TypsäkerhetFullständigSaknas (Any?)Fullständig
Retain cycle riskNej (weak)NejJa (fånga self)
När ska användasKomplexa callbacks med flera metoderHändelser som intresserar mångaEnkla closures med 1-2 callbacks

Delegate är optimal när en serie relaterade händelser ska skickas till en mottagare. NotificationCenter är bättre för broadcast-notifikationer. Closure — för enkla asynkrona operationer, som completion handler i URLSession.

Implementering av Delegate i Objective-C

Objective-C använder @protocol och @optional för att deklarera delegater. Till skillnad från Swift är alla protokollets metoder som standard valfria. Den viktigaste skillnaden — anrop av respondsToSelector: innan meddelandet skickas till delegaten, eftersom metoden kanske inte är implementerad.

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];
    }
    // asynkron bildladdning
}
@end

Den viktigaste skillnaden i Objective-C: före anrop av en valfri metod krävs kontroll av respondsToSelector:. I Swift eliminerar protokollets valfria metoder denna kontroll — optional chaining (?.) hanterar automatiskt fallet med saknad implementering.

Typiska fel vid arbete med delegater

Fel vid användning av delegater leder till minnesläckor, appkrascher och ouppenbara buggar. Låt oss titta på fem av de vanligaste problemen.

Stark referens till delegaten

Retain cycle — det vanligaste felet. Om delegate-egenskapen deklareras som strong, och delegaten i sin tur äger ägarobjektet, uppstår en retentionscykel. Båda objekten frigörs aldrig från minnet. Lösning: deklarera alltid delegaten som weak var i Swift eller @property (weak) i Objective-C.

Delegaten har inte nollställts efter dealloc

Om ägarobjektet överlever delegaten och referensen finns kvar, leder anrop av delegatens metod till EXC_BAD_ACCESS. Weak-referens löser detta problem automatiskt: efter att delegaten frigörs blir egenskapen nil. I flertrådade scenarier är det dock värt att kontrollera delegaten även i huvudtråden.

Överdrivet antal metoder i protokollet

Ett protokoll med 20+ metoder bryter mot principen om gränssnittsseparation (ISP). UITableViewDelegate innehåller cirka 30 valfria metoder — detta är ett historiskt undantag. I egna protokoll är det bättre att dela upp ansvaret i flera små protokoll, var och en med sin egen roll.

Exempel på Delegate i system-API:er för iOS

Apples system-API:er använder aktivt Delegate-mönstret. Låt oss titta på tre viktiga exempel från UIKit som förekommer i varje iOS-applikation.

APIProtokollNyckelmetoder
UITableViewUITableViewDelegatedidSelectRowAt, heightForRowAt, willDisplay
UITextFieldUITextFieldDelegateshouldChangeCharactersIn, didBeginEditing, shouldReturn
URLSessionURLSessionDelegatedidReceiveChallenge, didCompleteWithError, didBecomeInvalidWithError

Vart och ett av dessa protokoll implementerar olika aspekter av beteende: UITableViewDelegate hanterar utseende och reaktion på beröring, UITextFieldDelegate kontrollerar textinmatning, URLSessionDelegate bearbetar nätverkshändelser. Detta visar mönstrets flexibilitet: delegaten kan anpassas till vilket ansvarsområde som helst.

Vanliga frågor

Vad är skillnaden mellan delegate och dataSource i iOS?

Delegate hanterar beteende och utseende (cellhöjd, reaktion på beröring). DataSource tillhandahåller data (antal rader, cellinnehåll). UITableViewDelegate och UITableViewDataSource — det är två separata protokoll som delar ansvaret för presentation och data.

Varför deklareras delegate som weak?

Weak-referens förhindrar retain cycle. Ägaren (t.ex. UITableView) håller referensen till delegaten endast som weak. Om delegaten (UIViewController) äger tabellen skulle en stark referens till delegaten skapa en cykel: ViewController → UITableView → Delegate (ViewController). Weak bryter denna cykel.

Kan delegate användas i SwiftUI?

I SwiftUI används Delegate-mönstret mer sällan — det ersätts av @Binding, @State och closures. Dock används delegate fortfarande för UIKit-integration via UIViewRepresentable. Till exempel förblir MKMapViewDelegate och WKUIDelegate relevanta när UIKit-komponenter lindas in i SwiftUI.

Vad är @objc optional i Swift-protokoll?

@objc optional gör det möjligt att deklarera valfria metoder i ett Swift-protokoll. Detta är en kompatibilitetsmekanism med Objective-C runtime. Utan @objc är alla metoder i ett Swift-protokoll som standard obligatoriska. Optional används i UIKit-protokoll, där delegaten endast kan implementera de metoder den behöver.

Hur många delegater kan ett objekt ha?

Ett objekt kan ha endast en delegat för varje delegate-egenskap. Om flera objekt behöver meddelas, använd multicast delegate, en array av delegater eller NotificationCenter. Delegate-mönstret är ursprungligen utformat som en 1:1-relation.

Sammanfattning

  • Delegate — beteendedesignmönster som överför utförandet av en uppgift från ett objekt till ett annat via ett protokoll
  • Swift-protokoll deklarerar en uppsättning metoder; valfria metoder markeras med @objc optional, obligatoriska implementeras alltid
  • Weak-referens till delegaten är obligatorisk för att förhindra retain cycle och minnesläckor
  • UITableViewDelegate — det mest kända exemplet; dess metoder hanterar höjd, val och visning av celler
  • Delegate skiljer sig från NotificationCenter genom 1:1-relation kontra 1:N och fullständig typsäkerhet
  • Objective-C kräver kontroll av respondsToSelector: för valfria metoder, Swift hanterar detta automatiskt
  • Rekommendation: använd delegate för komplexa callbacks med flera relaterade metoder och closure för enkla slutningar

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också