Swinject: ano ito, mga prinsipyo ng Dependency Injection at paano ito gumagana

May-akda: IT Sectr Nai-publish: 2026-05-04 Oras ng pagbabasa: 8 min

Ang Swinject ay isang DI container para sa Swift na nagpapatupad ng pattern ng Dependency Injection sa mga iOS application. Awtomatiko ng framework ang paglikha at pag-inject ng mga dependency, inaalis ang manu-manong pamamahala ng mga object at factory. Ayon sa datos ng Swinject sa GitHub, sinusuportahan ng library ang Constructor Injection, Property Injection at Method Injection na may flexible na sistema ng mga scope para sa pamamahala ng habang-buhay.

Mga pangunahing punto

  • Swinject — DI container para sa Swift na nag-automate ng pag-inject ng dependency sa mga iOS project.
  • Dependency Injection — pattern kung saan ang object ay tumatanggap ng mga dependency mula sa labas, hindi gumagawa ng mga ito sa loob.
  • Container — sentral na bahagi ng Swinject na nag-iimbak ng rehistro ng mga rehistradong serbisyo at kanilang mga factory.
  • Service — abstraksyon sa anyo ng isang protocol kung saan ang container ay nag-iimbak ng isang kongkretong implementasyon.
  • ObjectScope — mekanismo na tumutukoy sa habang-buhay ng instance: graph, container o transient.

Ano ang Swinject at Dependency Injection

Swinject ay isang open-source na DI container para sa wikang Swift, na dinisenyo upang pasimplehin ang pag-inject ng dependency sa mga application para sa iOS, macOS at watchOS. Ang framework ay gumagamit ng Service Locator approach: ang mga serbisyo ay nirerehistro sa isang sentral na container, at ang container ay awtomatikong niresolba ang dependency graph kapag humihiling ng instance.

Ang Dependency Injection (DI) ay isang pattern ng disenyo kung saan ang object ay tumatanggap ng mga dependency nito mula sa labas, hindi gumagawa ng mga ito sa loob. Binabawasan nito ang pagkakabit sa pagitan ng mga bahagi, pinapasimple ang modular na pagsubok, at pinapayagan ang pagpapalit ng mga implementasyon nang hindi binabago ang code ng consumer.

Ayon kay Martin Fowler (2004), ang DI ay isang espesyal na kaso ng Inversion of Control at ipinapatupad sa pamamagitan ng pag-inject sa pamamagitan ng constructor, property o method. Awtomatiko ng Swinject ang prosesong ito, inaalis ang manu-manong pagsulat ng mga factory at service locator.

Ilapat ang Swinject sa mga project na may tatlo o higit pang serbisyo na may mga cross-dependency, kung saan ang manu-manong pagbuo ng object ay humahantong sa paglaki ng initialization code at pagbaba ng testability.

Ang Swinject ay malapit na sumasama sa Apple ecosystem at sinusuportahan ang lahat ng bersyon ng Swift simula sa 3.0. Ang framework ay tugma sa Objective-C sa pamamagitan ng mga tulay, na nagpapahintulot sa pag-deploy nito sa mga umiiral na project na nakasulat sa pinaghalong wika nang walang buong paglipat ng code. Ito ay partikular na mahalaga para sa malalaking application na may kasaysayan ng pag-develop na higit sa limang taon.

Paano gumagana ang Swinject container

Ang Swinject container ay ipinatupad ng klase na Container, na nag-iimbak ng rehistro ng mga rehistradong serbisyo. Kapag tinawag ang resolve method, ang container ay lumilikha ng object, na niresolba ang lahat ng dependency nito nang recursively ayon sa registration graph.

Container at Service

Container ay ang sentral na object kung saan nirerehistro ang mga korespondensya sa pagitan ng abstraksyon at ng implementasyon nito. Ang Service ay isang protocol na tumutukoy sa kontrata, at ang Component ay isang klase na nagpapatupad ng protocol na ito. Ang pagrerehistro ay ginagawa sa pamamagitan ng register method, na tumatanggap ng uri ng serbisyo at factory.

swift
let container = Container()
container.register(Networking.self) { _ in
    NetworkService()
}
let service = container.resolve(Networking.self)

Ang resolve method ay nagbabalik ng isang instance ng kongkretong implementasyon na nirerehistro para sa tinukoy na protocol. Kung ang dependency ay hindi nirerehistro, ang container ay nagtatapon ng isang nakamamatay na error para sa mabilis na pagtuklas ng problema sa yugto ng pag-develop.

Registration at mga pinangalanang serbisyo

Ang bawat pagrerehistro ay lumilikha ng entry na may factory function at napiling scope. Ang isang serbisyo ay maaaring magkaroon ng maraming pagrerehistro na may iba't ibang pangalan, na nagpapahintulot sa pagpili ng kongkretong implementasyon ayon sa pangalan — kapaki-pakinabang para sa iba't ibang kapaligiran (development, staging, production).

Ang proseso ng pagresolba ng dependency (resolution) ay gumagana nang recursively: kapag ang container ay lumilikha ng isang instance ng Component, sinusuri nito ang initializer nito at para sa bawat parameter ay tinatawagan ang resolve ng kaukulang uri. Kung ang dependency ay mayroon ding sariling mga dependency, ang proseso ay magpapatuloy hanggang ang buong graph ay ganap na mabuo. Ang lalim ng nesting ay limitado lamang ng magagamit na memorya, ngunit sa pagsasagawa ay bihirang lumampas sa limang antas.

Mga paraan ng pag-inject ng dependency sa Swinject

Swinject ay sumusuporta sa tatlong pangunahing paraan ng pag-inject ng dependency, bawat isa ay naaangkop depende sa konteksto ng arkitektura.

Constructor Injection

Constructor Injection — pag-inject ng dependency sa pamamagitan ng mga parameter ng initializer. Ito ang ginustong paraan, na ginagarantiyahan na ang object ay palaging nasa tamang estado mula sa sandali ng paglikha. Awtomatikong niresolba ng Swinject ang lahat ng dependency na ipinasa sa constructor.

swift
class LoginViewModel {
    private let authService: AuthProtocol

    init(authService: AuthProtocol) {
        self.authService = authService
    }
}

container.register(AuthProtocol.self) { _ in
    AuthService()
}
container.register(LoginViewModel.self) { r in
    LoginViewModel(authService: r.resolve(AuthProtocol.self)!)
}

Property Injection

Property Injection — pag-inject sa pamamagitan ng pagtatakda ng mga property ng object pagkatapos ng initialisasyon nito. Ginagamit kapag ang dependency ay opsyonal o hindi maaaring ipasa sa pamamagitan ng constructor, halimbawa kapag nagtatrabaho sa Storyboard, kung saan ang view controller ay awtomatikong nilikha. Sinusuportahan ng Swinject ang @Inject annotation para sa awtomatikong pag-inject ng property sa pamamagitan ng runtime nang walang tawag na resolve.

Sa paggamit ng Property Injection, mahalagang tiyakin na ang dependency ay naitakda bago ang unang pag-access sa object. Kung hindi, ang property ay mananatiling nil, na hahantong sa hindi inaasahang crash. Niresolba ng Swinject ang problemang ito sa pamamagitan ng mekanismong Implicitly Unwrapped Optional at mahigpit na pag-verify sa yugto ng pagresolba ng dependency graph.

Method Injection

Method Injection — pag-inject sa pamamagitan ng mga parameter ng method. Inilalapat para sa mga serbisyo na kailangan lamang para sa pagsasagawa ng isang operasyon at hindi dapat itago bilang permanenteng estado ng object. Ito ang hindi gaanong karaniwan, ngunit kapaki-pakinabang para sa mga callback na paraan ng pag-inject.

Mga scope sa Swinject at ang kanilang gamit

ObjectScope — mekanismo na tumutukoy sa habang-buhay ng nilikhang instance sa loob ng Swinject container. Ang framework ay nagbibigay ng tatlong built-in na scope na may kakayahang lumikha ng mga custom na scope sa pamamagitan ng ObjectScopeProtocol.

ObjectScope.graph

Ang graph scope — default na halaga. Sa bawat tawag sa resolve, isang bagong instance ang nilikha na nabubuhay lamang sa tagal ng pagresolba ng dependency graph. Ito ay isang ligtas na pagpipilian para sa mga serbisyong walang estado dahil inaalis nito ang pagtagas ng memorya dahil sa caching.

ObjectScope.container

Ang container scope — singleton sa loob ng container. Ang instance ay nilikha nang isang beses sa unang resolve at ibinabalik sa lahat ng kasunod na kahilingan. Angkop para sa mga serbisyo na may nakabahaging estado: data cache, logger, mga setting ng application.

ObjectScope.transient

Ang transient scope — bawat tawag sa resolve ay lumilikha ng bagong instance nang walang caching. Ginagamit para sa mga magaan na object na hindi kailangang gamitin muli — halimbawa, para sa mga module na nagtatrabaho sa isang partikular na HTTP request.

ScopeHanggang-buhayGamit
graphSa tagal ng pagresolba ng graphMga serbisyong walang estado bilang default
containerBuong habang-buhay ng containerSingleton: cache, logger, network client
transientWalang cachingMga magaan na object para sa isang beses na paggamit

Swinject sa mga iOS project

Ang pagsasama ng Swinject sa isang tunay na iOS project ay nagsisimula sa initialisasyon ng container sa pagsisimula ng application — sa AppDelegate o scene. Inirerekomenda na istraktura ang mga pagrerehistro sa pamamagitan ng Assembly: isang hiwalay na klase o istraktura na nagpapangkat ng mga kaugnay na serbisyo.

Ayon sa survey ng Swift Developer Community (2025), 43% ng mga iOS developer ay gumagamit ng DI container sa mga komersyal na project para sa pamamahala ng mga dependency ng network layer, repository at navigation coordinator. Ang Swinject ay nananatiling pinakasikat na solusyon dahil sa minimal na syntax at pagiging tugma sa Objective-C.

Storyboard Injection — natatanging kakayahan ng Swinject: ang container ay awtomatikong nag-iinject ng mga dependency sa mga view controller na nilikha mula sa Storyboard, nang walang karagdagang code sa AppDelegate. Para dito, ginagamit ang isang espesyal na resolver na ipinapasa sa UIStoryboard sa pamamagitan ng init(container:) method, na humaharang sa paglikha ng view controller at nag-iinject ng mga rehistradong dependency.

Sa malalaking project, ang Swinject ay maaaring pagsamahin sa mga navigation coordinator: ang coordinator ay tumatanggap ng container at lumilikha ng mga screen, nireresolba ang kanilang mga dependency sa pamamagitan ng resolve, na nagpapanatili ng isang configuration point para sa buong scene.

Arkitektura na may Assembly — ang inirerekomendang pattern para sa pag-oorganisa ng mga pagrerehistro. Ang bawat Assembly ay nagpapangkat ng mga kaugnay na serbisyo (hal. NetworkingAssembly, DatabaseAssembly) at maaaring umasa sa iba pang Assembly. Sa initialisasyon ng container, lahat ng Assembly ay naglo-load at nagrerehistro ng kanilang mga serbisyo, na nagbibigay ng malinaw na paghihiwalay ng responsibilidad at pinapasimple ang nabigasyon sa pamamagitan ng DI configuration sa malalaking project na may dose-dosenang serbisyo.

Para sa pag-debug ng DI graph, ang Swinject ay nagbibigay ng extension na SwinjectPropertyLoader, na naglo-load ng configuration mula sa isang plist file, at SwinjectStoryboard — pagsasama sa mga storyboard sa pamamagitan ng isang espesyal na bersyon ng UIStoryboard. Ang mga tool na ito ay partikular na kapaki-pakinabang sa yugto ng paglipat ng isang umiiral na project mula sa manu-manong pagbuo ng object patungo sa DI: ang developer ay maaaring unti-unting magrehistro ng mga serbisyo, suriin ang dependency graph sa pamamagitan ng mga pagsubok at pag-log ng mga error sa pagresolba, nang hindi humihinto sa pag-develop ng mga pangunahing feature ng application.

Ang Swinject ay nagbibigay din ng pagsasama sa RxSwift at Combine sa pamamagitan ng extension na SwinjectAutoregistration para sa awtomatikong pagresolba ng dependency ayon sa mga uri ng parameter ng initializer nang walang tahasang pagrerehistro ng factory. Binabawasan nito ang dami ng registration code para sa mga simpleng serbisyo: sapat na ang tumawag ng container.register(ServiceProtocol.self) nang hindi tinukoy ang factory, at ang Swinject ay nakapag-iisa na bubuo ng factory batay sa Signal reflection na ibinigay ng Swift runtime. Ang approach na ito ay inirerekomenda para sa mga serbisyo na ang constructor ay tumatanggap lamang ng mga base type at hindi nangangailangan ng kumplikadong lohika sa paglikha.

Mga madalas itanong

Paano naiiba ang Swinject sa iba pang DI framework para sa Swift?

Swinject ay isinulat sa purong Swift nang walang code generation at reflection. Hindi tulad ng Needle, hindi ito nangangailangan ng pagbuo ng source code, at kumpara sa Dip — nagbibigay ito ng built-in na suporta para sa Storyboard Injection, na pinapasimple ang pagsasama sa mga umiiral na UIKit project.

Paano i-install ang Swinject sa pamamagitan ng Swift Package Manager?

Idagdag ang package sa pamamagitan ng URL github.com/Swinject/Swinject sa pamamagitan ng Xcode sa menu File — Add Packages. Available din ang pag-install sa pamamagitan ng CocoaPods at Carthage. Pagkatapos ng pag-install, i-import ang Swinject module at lumikha ng isang instance ng Container.

Maaari bang gamitin ang Swinject sa mga SwiftUI project?

Oo, ang Swinject ay ganap na tugma sa SwiftUI. Ang mga dependency ay ini-inject sa pamamagitan ng View initializer o sa pamamagitan ng Environment, kung saan ang container ay ipinapasa bilang EnvironmentObject. Ang Swinject ay hindi nakadepende sa UIKit at gumagana nang pareho sa parehong framework.

Paano gamitin ang Swinject para sa modular na pagsubok?

Lumikha ng isang hiwalay na container para sa mga pagsubok, palitan ang mga tunay na serbisyo ng mga mock. Pinapayagan ng Swinject ang pag-override ng mga pagrerehistro nang hindi binabago ang code ng consumer. Ang bawat pagsubok ay nakakakuha ng isang isolated na container na may minimal na set ng dependency.

Aling scope ang pipiliin para sa analytics service?

Para sa analytics gamitin ang container scope, upang ang lahat ng screen ay magpadala ng mga event sa pamamagitan ng isang instance. Ginagarantiyahan nito ang isang pare-parehong queue ng pagpapadala at tamang batch aggregation nang walang pagdoble ng data sa pagitan ng iba't ibang consumer.

Buod

  • Swinject — DI container para sa Swift na nag-automate ng pag-inject ng dependency sa pamamagitan ng Container at ObjectScope.
  • Binabawasan ng Dependency Injection ang pagkakabit ng code, pinapasimple ang pagsubok, at pinapayagan ang pagpapalit ng implementasyon nang hindi binabago ang mga consumer.
  • Container — rehistro ng serbisyo na sumusuporta sa register para sa pagrerehistro at resolve para sa pagkuha ng instance.
  • Constructor Injection — ang ginustong paraan ng pag-inject, na ginagarantiyahan ang tamang estado ng object.
  • ObjectScope ay namamahala ng habang-buhay: graph (default), container (singleton) at transient (walang cache).
  • Awtomatikong nag-iinject ang Storyboard Injection ng mga dependency sa UIKit scene nang walang manu-manong configuration.
  • Para sa modular na pagsubok, gumamit ng hiwalay na container na may mock implementasyon ng mga serbisyo.

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