Delegate: ano ito, pattern ng delegasyon at paano ito gumagana sa iOS

May-akda: IT Sectr Nai-publish: 2026-03-17 Oras ng pagbabasa: 10 min

Delegate — ay isang pattern ng disenyo kung saan ang isang bagay ay nagde-delegate ng pagpapatupad ng mga gawain sa ibang bagay sa pamamagitan ng isang protokol na may paunang natukoy na mga metodo. Sa iOS development, ang Delegate ay isa sa mga pangunahing pattern ng Cocoa Touch, na ginagamit para sa asinkronong notipikasyon nang walang direktang koneksyon sa pagitan ng tagapadala at tagatanggap. Ayon sa Apple Documentation (2025), ang delegasyon ay inilalapat sa Foundation at UIKit para sa pagproseso ng mga event ng talahanayan, mga kahilingan sa network, at pamamahala ng lokasyon. Tinitiyak ng pattern ang mahinang pagkakabit ng mga bahagi at muling paggamit ng code.

Mga Pangunahing Punto

  • Delegate — pattern kung saan ipinagkakatiwala ng bagay ang pagproseso ng mga event sa ibang bagay sa pamamagitan ng protokol.
  • Protocol sa Swift ay tumutukoy sa hanay ng mga metodo na dapat o maaaring ipatupad ng delegate.
  • Weak reference ay kinakailangan para sa property na delegate upang maiwasan ang retain cycle.
  • @objc optional ay nagpapahintulot na gawing opsyonal ang mga metodo ng protokol para sa implementasyon.
  • URLSessionDelegate — asinkronong delegate para sa pagproseso ng mga event ng kahilingan sa network.

Ano ang Delegate?

Delegate (delegado) — ay isang bagay na nagpapatupad ng isang tiyak na protokol at tumatanggap ng mga notipikasyon tungkol sa mga event ng ibang bagay. Ang pattern ng Delegation ay isang alternatibo sa pagmamana: sa halip na lumikha ng isang subclass para sa pag-override ng mga metodo, ang bagay ay nagde-delegate ng pagproseso ng event sa isang panlabas na bagay. Sa iOS, ang delegation ay ipinatupad sa pamamagitan ng Swift protokol na may sapilitan at opsyonal na mga metodo. Ang property na delegate ay palaging idineklara bilang weak var upang maiwasan ang mga paikot na sanggunian sa pagitan ng mga bagay.

Pagtukoy sa Protokol ng Delegate

Ang protokol ng delegate ay tumutukoy sa kontrata ng interaksyon sa pagitan ng mga bagay. Sapilitang metodo ay dapat ipatupad ng delegado, kung hindi ang code ay hindi magko-compile. Opsyonal na metodo ay minamarkahan ng attribute na @objc optional at pinapayagan ang delegado na tumugon lamang sa mga kinakailangang event. Ang mga pangalan ng metodo ay sumusunod sa kombensiyon: unang parameter — bagay na tagapadala, pangalawa — data ng event. Halimbawa, ang tableView(_:didSelectRowAt:) ay nagpapahiwatig na ang tagapadala ay UITableView, at ang data ay ang index ng napiling row.

swift
// Protokol ng Delegate
protocol DownloadManagerDelegate: AnyObject {
    func downloadManager(_ manager: DownloadManager,
                          didFinishWith data: Data)
    func downloadManager(_ manager: DownloadManager,
                          didFailWith error: Error)

    @objc optional func downloadManager(_ manager: DownloadManager,
                                didUpdateProgress progress: Float)
}

// Klase na gumagamit ng Delegate
class DownloadManager {
    weak var delegate: DownloadManagerDelegate?

    func startDownload(from url: URL) {
        URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
            guard let self else { return }
            if let error = error {
                self.delegate?.downloadManager(self, didFailWith: error)
            } else if let data = data {
                self.delegate?.downloadManager(self, didFinishWith: data)
            }
        }.resume()
    }
}

Mahinang sanggunian sa delegate

Ang property na delegate ay dapat ideklara bilang weak var (mahinang pointer) upang maiwasan ang retain cycle. Kung ang sanggunian ay malakas, ang delegado at ang nagde-delegate na bagay ay hahawak sa isa't isa, at hindi mapapalaya ng ARC ang kanilang memorya. Ang mga protokol ng delegate ay nagmamana ng AnyObject (para lamang sa mga klase), na nagpapahintulot sa paggamit ng weak. Ang mga istraktura at enum ay hindi maaaring maging delegado dahil sa semantika ng halaga. Alternatibo para sa value types — callback closures.

swift
class ViewController: DownloadManagerDelegate {
    let manager = DownloadManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        manager.delegate = self // weak — walang retain cycle
        manager.startDownload(from: url)
    }

    func downloadManager(_ manager: DownloadManager, didFinishWith data: Data) {
        processData(data)
    }

    func downloadManager(_ manager: DownloadManager, didFailWith error: Error) {
        showError(error)
    }
}

Paano gumagana ang pattern ng Delegate sa iOS?

Ang pattern ng Delegate ay gumagana sa prinsipyong “isa-sa-isa”: isang bagay na tagapadala ay maaaring magkaroon lamang ng isang delegado sa isang partikular na oras. Kapag naganap ang isang event, sinusuri ng tagapadala kung nakatakda ang delegate, at tinatawagan ang kaukulang metodo ng protokol. Bentahe kumpara sa direktang tawag — hindi alam ng tagapadala ang uri ng delegado, alam lamang na ito ay tumutugon sa protokol. Ito ay sumusunod sa prinsipyo ng dependency inversion (DIP) mula sa SOLID.

Ikot ng buhay ng delegado

Ang delegado ay itinatakda sa pamamagitan ng pagtatalaga: someObject.delegate = self. Sa dealokasyon ng delegado, ang property ay awtomatikong nagiging nil dahil sa weak semantika. Bago tawagan ang metodo ng delegate, sinusuri sa pamamagitan ng optional chaining: delegate?.method(). Kung ang delegate ay nil — ang tawag ay hindi pinapansin nang walang crash. Para sa opsyonal na metodo ng protokol, ginagamit ang karagdagang pagsusuri: delegate?.responds(to: #selector(...)), bagaman sa Swift ang pagsusuri na ito ay karaniwang implicit sa pamamagitan ng deklarasyon ng opsyonal na metodo.

Asinkronong notipikasyon sa pamamagitan ng Delegate

Sa multi-threaded na kapaligiran, ang delegate ay ginagamit para sa asinkronong pagbabalik ng resulta. URLSession ay nagbibigay ng URLSessionDelegate na may mga metodo na tinatawag kapag nakatanggap ng data, timeout, o error sa pagpapatotoo. Ang mga metodo ng delegate ay isinasagawa sa background queue ng URLSession, kaya kinakailangan ang dispatch sa main queue para sa mga update sa UI. Ang asinkronong delegate ay hindi humaharang sa tumatawag na thread, na nagpapahintulot sa pagpapatuloy ng ibang mga gawain.

swift
class NetworkService: NSObject, URLSessionDataDelegate {
    private lazy var session = URLSession(
        configuration: .default,
        delegate: self,
        delegateQueue: OperationQueue()
    )
    private var receivedData = Data()

    func urlSession(_ session: URLSession,
                    dataTask: URLSessionDataTask,
                    didReceive data: Data) {
        receivedData.append(data)
        let progress = Float(receivedData.count) / Float(expectedSize)
        DispatchQueue.main.async {
            self.progressHandler?(progress)
        }
    }

    func urlSession(_ session: URLSession,
                    task: URLSessionTask,
                    didCompleteWithError error: Error?) {
        if let error = error {
            delegate?.networkService(self, didFailWith: error)
        } else {
            delegate?.networkService(self, didReceive: receivedData)
        }
    }
}

Delegate vs Callback: paghahambing ng mga approach

Delegate at Callback ay lumulutas ng parehong gawain — asinkronong notipikasyon — ngunit sa magkaibang paraan. Ang Delegate ay gumagamit ng protokol na may pinangalanang metodo, ang callback — closure na may pagkuha ng konteksto. Ang pagpili ay depende sa bilang ng mga event, pagiging kumplikado ng mga lagda, at mga kagustuhan sa arkitektura. Inirerekomenda ng Apple ang delegate para sa mga API na may maraming event (UITableView — 20+ metodo) at callback para sa isang beses na pagkumpleto.

Kailan nananalo ang Delegate

Ang Delegate ay mas gusto kapag kailangan iproseso ang maraming iba't ibang event mula sa isang mapagkukunan. Halimbawa, CLLocationManager ay nagpapaalam sa delegado tungkol sa pagbabago ng lokasyon, mga error sa pahintulot, pagpasok/paglabas sa mga geozone, at pagbabago ng katayuan ng serbisyo. Ang bawat event ay isang hiwalay na metodo ng protokol na may malinaw na pangalan at naka-type na mga parameter. Ang Delegate ay maginhawa rin para sa pagsasaayos ng pag-uugali (should, will, did na metodo).

Kailan nananalo ang Callback

Ang Callback ay mas simple para sa isang beses na kahilingan na may isang resulta. Completion handler sa URLSession.dataTask ay sumasakop ng isang linya sa punto ng tawag kumpara sa hindi bababa sa tatlong metodo ng protokol. Ang Callback ay mas natural din para sa functional chain (map, flatMap, async/await). Gayunpaman, kapag nesting nang higit sa 2-3 antas, ang callback ay nagiging Callback Hell, habang ang delegate ay palaging nananatiling flat.

Mga Built-in na Delegate sa iOS SDK

Ang iOS SDK ay naglalaman ng dose-dosenang mga built-in na protokol ng delegate para sa iba't ibang subsystem. Ang bawat isa ay dinisenyo para sa isang tiyak na senaryo ng interaksyon. Ayon sa Apple Documentation (2025), ang pinakamadalas gamitin na delegate ay UITableViewDelegate, UITextFieldDelegate, CLLocationManagerDelegate, URLSessionDelegate at UNUserNotificationCenterDelegate. Ang mga protokol na ito ay naglalaman ng 3 hanggang 30 metodo na may iba't ibang antas ng obligasyon.

UITableViewDelegate

UITableViewDelegate ay namamahala sa hitsura at pag-uugali ng mga cell ng talahanayan. Naglalaman ng mga metodo para sa pagproseso ng pagpili ng row, pagtatakda ng taas ng cell, mga kustom na view ng header/footer, at mga swipe action. Lahat ng metodo ng protokol ay opsyonal, na nagpapahintulot na ipatupad lamang ang kinakailangang functionality. Kapag walang delegado, ang talahanayan ay gumagana sa default na mga setting. Sa kasaysayan, ang delegate ay pinagsama sa UITableViewDataSource.

URLSessionDelegate

URLSessionDelegate ay nagbibigay ng detalyadong kontrol sa mga kahilingan HTTP. Ang mga metodo ng delegado ay tinatawag kapag nakatanggap ng tugon ng server, data, pagkumpleto ng pag-download. Ang mga espesyalisadong subprotocol na URLSessionTaskDelegate at URLSessionDataDelegate ay nagpapalawak ng pangunahing functionality para sa mga tiyak na uri ng gawain. Ang Delegate ay kinakailangan para sa suporta ng background download, SSL certificate, at kustom na pagproseso ng mga redirect.

DelegateMetodoLayunin
UITableViewDelegate25Hitsura at interaksyon sa talahanayan
UITextFieldDelegate8Pagproseso ng input ng teksto at keyboard
CLLocationManagerDelegate12Pag-update ng lokasyon at mga geozone
URLSessionDelegate6Pamamahala ng HTTP session at mga certificate
UNUserNotificationCenterDelegate4Pagproseso ng push notification sa foreground

Pamamahala ng Memorya sa Paggawa gamit ang Delegate

Ang pamamahala ng memorya ay isang kritikal na aspeto ng paggawa gamit ang delegate sa iOS. ARC (Automatic Reference Counting) ay awtomatikong namamahala ng memorya, ngunit lamang sa tamang paggamit ng weak/unowned na sanggunian. Ang paglabag sa mga patakaran ay humahantong sa pagtagas ng memorya o napaaga na dealokasyon. Ang delegate na idineklara bilang strong ay lumilikha ng retain cycle kung ang may-ari ng delegado ay nagtatago rin ng sanggunian sa nagde-delegate na bagay.

Retain cycle sa pamamagitan ng Delegate

Ang retain cycle ay nangyayari kapag ang bagay A (may-ari) ay nagtatakda ng sarili bilang delegado ng bagay B, at B ay nagtatago ng malakas na sanggunian sa delegate. Halimbawa: Ang ViewController ay lumilikha ng URLSession, nagtatakda ng self bilang delegado ng session, ngunit ang URLSession ay default na nagtatago ng malakas na sanggunian sa delegate kung walang tinukoy na delegateQueue. Solusyon — palaging suriin ang dokumentasyon ng API para sa uri ng sanggunian sa delegate (weak o strong) at tahasang itakda ang delegate sa nil sa deinit.

swift
class SafeViewController: UIViewController {
    private var session: URLSession?
    private var service: NetworkService?

    override func viewDidLoad() {
        super.viewDidLoad()
        service = NetworkService()
        service?.delegate = self
    }

    deinit {
        // Pagtatakda ng delegate sa nil sa deinit — best practice
        service?.delegate = nil
        session?.invalidateAndCancel()
    }
}

// URLSession na may weak delegate sa pamamagitan ng NSObject
class WeakDelegateSession: NSObject {
    private weak var delegate: URLSessionDelegate?

    func createSession() -> URLSession {
        let queue = OperationQueue()
        queue.maxConcurrentOperationCount = 1
        return URLSession(
            configuration: .default,
            delegate: self,
            delegateQueue: queue
        )
    }
}

Ligtas na pagsusuri ng delegate bago tawagan

Bago tawagan ang metodo ng delegado, kailangan suriin na ang delegado ay umiiral (hindi nil) at nagpapatupad ng tinatawag na metodo. Para sa sapilitang metodo ng protokol, hindi kinakailangan ang pagsusuri — ginagarantiyahan ng compiler ang implementasyon. Para sa opsyonal na metodo gamitin ang respond(to:) o optional chaining. Kung ang delegado ay na-deallocate, ang weak na sanggunian ay awtomatikong nagiging nil, at ang tawag sa delegado ay hindi pinapansin. Ito ay ligtas na pag-uugali na hindi nangangailangan ng karagdagang pagproseso.

Mga Karaniwang Pagkakamali sa Implementasyon ng Delegate

Ang mga developer ay madalas nagkakamali sa paggawa gamit ang pattern ng Delegate, lalo na sa mga unang yugto ng pag-aaral ng iOS. Pinakakaraniwan: retain cycle dahil sa strong delegate, nakalimutang tawagan ang delegate?.method(), maling lagda ng metodo ng protokol, pagtatakda ng delegate pagkatapos simulan ang operasyon, at multi-thread na banggaan. Tingnan natin ang bawat pagkakamali at mga paraan upang maiwasan ang mga ito.

Strong reference sa halip na weak

Ang pinakamahalagang pagkakamali — pagdedeklara ng property na delegate bilang strong var sa halip na weak var. Ito ay lumilikha ng retain cycle kung saan ang delegado at ang nagde-delegate na bagay ay hindi maaaring palayain. Mga resulta: pagtagas ng memorya, pagbagal ng aplikasyon, at mga nakatagong bug. Solusyon: palaging gumamit ng weak var para sa delegate, at ipamana ang protokol mula sa AnyObject upang ibukod ang paggamit ng value types bilang delegado.

Pagtatakda ng delegate pagkatapos simulan ang operasyon

Kung ang delegate ay itinakda pagkatapos tawagan ang isang asinkronong metodo, ang mga unang event ay maaaring mawala. Halimbawa: pagtawag ng startDownload() bago ang pagtatalaga ng manager.delegate = self ay humahantong sa pagkawala ng callback ng pagkumpleto, kung ang pag-download ay isinasagawa nang sabay o napakabilis. Solusyon: itakda ang delegate bago tawagan ang asinkronong metodo at idokumento ang pagkakasunud-sunod ng pagsisimula sa mga komento ng protokol.

Mga Madalas Itanong

Bakit ang delegate ay idineklara bilang weak?

Weak ay pumipigil sa retain cycle sa pagitan ng delegado at ng nagde-delegate na bagay. Kung ang sanggunian ay malakas, ang mga bagay ay hahawak sa isa't isa, at hindi sila mapapalaya ng ARC. Ang weak-sanggunian ay awtomatikong nagiging nil sa dealokasyon ng delegado. Ito ay karaniwang kasanayan ng Cocoa Touch mula noong paglitaw ng Objective-C at napanatili sa Swift para sa backward compatibility.

Ano ang pagkakaiba ng delegate at dataSource?

Delegate ay nagpoproseso ng mga event at namamahala ng pag-uugali (taas ng cell, reaksyon sa pag-click). DataSource ay nagbibigay ng data para ipakita (bilang ng row, cell). Ang Delegate ay sumasagot sa tanong na “paano?”, ang dataSource — sa tanong na “ano?”. Sa iOS, pareho ay ipinatupad sa pamamagitan ng protokol, madalas sa parehong controller, ngunit konseptwal na hiwalay.

Maaari bang gamitin ang struct bilang delegate?

Hindi, kung ang protokol ay nagmamana ng AnyObject (class protocol). Ang weak-sanggunian ay magagamit lamang para sa reference types (mga klase). Para sa value types (struct, enum) gumamit ng callback closure o hiwalay na wrapper class. Kung kontrolado mo ang protokol, maaari mong hindi mamana ang AnyObject, ngunit pagkatapos ang weak ay ipinagbabawal — pumili nang may kamalayan sa pagitan ng weak-delegate at struct-delegado.

Ano ang metodo na responds(to:) at para saan ito?

responds(to:) — ay isang metodo ng NSObjectProtocol na sumusuri kung ang bagay ay nagpapatupad ng tinukoy na selector. Ginagamit para suriin ang opsyonal na @objc metodo ng protokol bago tawagan. Kung walang pagsusuri na ito, ang pagtawag sa hindi ipinatupad na opsyonal na metodo ay magdudulot ng NSInvalidArgumentException. Sa Swift para sa mga protokol na may @objc optional, ang pagsusuri ay maaaring implicit sa pamamagitan ng optional binding.

Ang Delegate ba ay singleton?

Hindi, ang delegate ay isang pattern ng delegasyon, hindi singleton. Hindi tulad ng singleton, ang delegado ay maaaring palitan sa runtime at umiiral sa isang instance para sa bawat nagde-delegate na bagay. Isang bagay ay maaaring maging delegado para sa maraming tagapadala. Ang Singleton ay isang creational pattern na ginagarantiyahan ang nag-iisang instance ng isang klase at walang kinalaman sa delegasyon.

Buod

  • Delegate — pattern kung saan ang bagay ay nagde-delegate ng pagproseso ng event sa ibang bagay sa pamamagitan ng protokol na may naka-type na metodo.
  • Weak var ay kinakailangan para sa property na delegate upang maiwasan ang retain cycle at pagtagas ng memorya.
  • Protokol ay tumutukoy sa sapilitan at opsyonal (@objc optional) na metodo ng delegasyon.
  • iOS SDK ay naglalaman ng 15+ built-in na protokol ng delegate: UITableViewDelegate, URLSessionDelegate, CLLocationManagerDelegate.
  • Delegate ay mas gusto kaysa callback kapag may 3+ iba't ibang event mula sa isang source (CLLocationManager).
  • Asinkronong delegate ay ginagamit sa URLSession para makakuha ng data at progreso nang hindi hinaharangan ang thread.
  • Itakda ang delegate bago simulan ang asinkronong operasyon at itakda sa nil sa deinit para sa ligtas na pamamahala ng memorya.

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din