napsal Reinder de Vries dne 10. ledna 2019 v App Development, Swift

singleton je třída, z níž existuje přesně jedna instance, ke které lze přistupovat globálně. Jak vytvoříte singleton ve Swiftu? A proč byste měli nebo neměli?

v tomto tutoriálu se ponoříme do singletonů ve Swiftu. Dozvíte se, jaký je designový vzor singleton a proč je užitečný. Budeme diskutovat o syntaxi pro vytváření singletonů ve Swiftu. A dostaneme se do dobrých a špatných případů použití pro singletony.

připraven? Jdeme.

  1. Co Je Singleton?
  2. Kódování Singletonu V Swift
  3. Kdy Použít Singletony
  4. Další Čtení

Co Je Singleton?

singleton je třída, z níž existuje pouze jedna instance. Několik příkladů:

  • společnost má pouze jednu CEO
  • třída API má pouze jednu frontu sériových požadavků
  • operační systém má pouze jeden souborový systém
  • tělo sluneční soustavy se točí kolem jednoho gravitačního bodu
  • aplikace, která dělá I/O, má pouze jednu výchozí FileManager
  • letadlo má pouze jednu letovou palubu

druhá atribut singletonu je, že má globální přístupový bod. Můžete přistupovat k singletonu, např. funkce volání na něm, odkudkoli v kódu aplikace.

takže shrnout:

  1. singleton je třída, která má pouze jednu instanci
  2. je přístupná globálně, tj. kdekoli ve vašem kódu

při praktickém vývoji iOS často používáte singletony. Typické třídy jako NotificationCenter, UserDefaults, SKPaymentQueue a FileManager mají shared nebo default vlastnosti, které jsou singletony.

jindy si možná budete chtít vytvořit singleton sami. Dobrým případem použití je třída API, která odhaluje instanci singleton prostřednictvím své vlastnosti shared. Používáte API.shared.makeAPICall() pro přístup k API prostřednictvím jediné jednotné instance. To vám například umožňuje sériově spravovat volání API.

než budeme diskutovat o tom, kdy se singletony nejlépe používají (a kdy ne), zjistíme, jak kódovat singleton v Swift.

získejte najat jako vývojář iOS

Naučte se vytvářet aplikace pro iOS 14 pomocí Swift 5

přihlaste se do mého kurzu vývoje iOS a naučte se, jak začít svou kariéru jako profesionální vývojář iOS.

kódování singletonu v Swift

Toto je nejlepší způsob, jak vytvořit singleton v Swift:

class API{ static let shared = API() private init() { // Set up API instance }}

a zde je návod, jak používat singleton:

API.shared.doSomething()

vytváříme třídu API, která má jednu statickou vlastnost nazvanou shared. Tuto vlastnost nelze po nastavení změnit, protože je konstanta a je deklarována staticky.

to znamená, že můžeme přistupovat k vlastnosti shared prostřednictvím třídy API. Toto se často nazývá vlastnost třídy. Porovnejte to s normální vlastností instance, ke které lze přistupovat pouze prostřednictvím instance třídy.

zajímavé je, že vlastnost shared inicializuje instanci API ve třídě API. Vytváříme objekt API, ke kterému lze přistupovat prostřednictvím třídy API. Ale je toho víc…

inicializátor třídy init() je označen private. Toto klíčové slovo private zajišťuje, že třídu API lze inicializovat pouze ve třídě API.

jinými slovy, nemůžete vytvořit instanci API mimo třídu API! Tím je zajištěno, že objekt API, který jsme vytvořili, je jedinou instancí v našem kódu. Koneckonců, nemůžete vytvořit více z toho.

a nyní jsme zajistili, že třída API odpovídá dvěma atributům singletonu:

  1. díky statické vlastnosti shared je instance API přístupná globálně
  2. díky private init() nelze třídu API inicializovat mimo třídu API

to vše vám může znít trochu abstraktně, takže rozšířme předchozí příklad o nějaký praktičtější kód. Zde je co:

třída API je většinou stejná. Je to stále singleton a stále používá ty static let shared = API() a private init() bitů kódu.

zde je to, co se změnilo:

  • třída API má nyní vlastnost isRequestPending. Zde začíná nebezpečí… podívejte se, jak isRequestPending boolean zajišťuje, že lze současně provést pouze jeden požadavek API? (Všimněte si, že isRequestPending je vlastnost instance.)
  • třída API má také funkci makeAPIRequest(). Představte si, že tuto funkci můžeme použít k získání některých dat zpět z API webové služby, jako je Twitter. ve funkci můžete vidět, že žádost lze podat pouze v případě, že aktuálně nevyřízena žádná jiná žádost.
  • třída API má také funkci onReturnAPIRequest(). Tato funkce je vyvolána při návratu požadavku API, tj. online data byla stažena do aplikace. isRequestPending boolean je znovu nastaven na false a data požadavku jsou zpracována.

a zde je návod, jak můžeme použít API singleton kdekoli v našem kódu:

API.shared.makeAPIRequest()

je tu ještě něco, co musíme probrat. Třída API nyní spravuje něco, co se nazývá stát. Můžete vidět „stát“ jako pocit: jste buď šťastní, nebo jste smutní, nebo jste naštvaní a tak dále. Můžete přepnout z jednoho stavu do druhého.

Třída API může přepínat mezi dvěma stavy:

  • stav, ve kterém isRequestPending je false
  • stav, ve kterém isRequestPending je true

jak se dozvíte v další části, stát a singletons mohou způsobit nejrůznější zmatek ve vašem kódu. Správa státu špatně je jediným největším důvodem zneužití singleton.

kdy používat singletony

kdy používáte singletony? Kniha Design Patterns: Elements of Reusable Object-Oriented Software by the Gang of Four má následující slova. Použijte vzor singleton, když:

  • musí existovat přesně jedna instance třídy a musí být přístupná klientům ze známého přístupového bodu
  • , pokud by měla být jediná instance rozšiřitelná podtřídou a klienti by měli mít možnost používat rozšířenou instanci bez úpravy jejich kódu

to je složité, ale to, co se scvrkává, je to, co je:

  • použijte singleton, když váš kód nevyžaduje více než jednu instanci třídy (tj. CEO ve společnosti)
  • a když musí být přístupný odkudkoli ve vašem kódu (tj., souborový systém)

dalším případem použití je podtřída. Globální proměnnou ve vašem kódu nelze snadno podklasifikovat, proto používáte třídu singleton. Kromě toho mohou být singletony testovány jednotkou pomocí injekce závislostí. Instanci API nahradíte instancí APIMock a získáte možnost jednotkových testovacích volání API bez provedení skutečných požadavků na síť.

a kdy nepoužíváte singletony? Abychom na tuto otázku odpověděli, musíme se vrátit ke státnímu principu, o kterém jsme hovořili dříve.

společným úskalím pro začínající vývojáře iOS je špatná správa stavu a jeho závislostí. Představte si, že vytváříte aplikaci, která používá třídu API, se kterou jsme dříve pracovali.

pokaždé, když rozšiřujete třídu API, získáte další a další vlastnosti, jako například:

  • vlastnost userID, která sleduje přihlášeného uživatele, jakmile je volání API login() provedeno
  • vlastnost tweets s daty Twitteru, jakmile je volání getTweets() provedeno
  • vlastnost spinner s UIActivityIndicatorView, kterou přidáte do řadiče zobrazení, když byl požadavek spuštěn

zpočátku, to dává velký smysl. Koneckonců, třída API je přístupná kdekoli ve vašem kódu. Takže v řadiči zobrazení tweetu můžete použít pole API.shared.tweets a v řadiči nastavení můžete pomocí userID rychle říct API, jehož nastavení se má změnit.

bohužel, váš stav je nyní všude. Třída API má závislosti na spoustě tříd, které nesouvisejí s jedinou odpovědností třídy API. Váš kód se stal miskou špaget, vše zamotané. Kód může fungovat dobře, ale není možné jej udržovat a rozšiřovat.

podívejme se na příklad. Funkce onReturnAPIRequest(), kterou jsme definovali dříve, je na pokraji těsného spojení …

zde je to, co zvažujeme:

  • onReturnAPIRequest() se volá, když se žádost o webovou službu API vrátí, tj. Tato data musí někam jít-například řadič zobrazení tweetu. Jak předáváte data z API do řadiče zobrazení?
  • jasnou volbou je pouze vytvoření odkazu na viewController ve třídě API. Když data přicházejí, můžete kódovat něco jako viewController.tweets = tweetsData. To je bohužel špatná Architektura, protože nyní jsou API a řadič zobrazení pevně spojeny. Je nemožné (nebo těžké) testovat jednotky a pravděpodobně způsobí problémy při rozšiřování jedné třídy.
  • je lepší zvolit mechanismus, který obě třídy těsně nespojí. Jednou z možností by bylo předat uzávěr onReturnAPIRequest(), který se provede, když se požadavek vrátí. Toto uzavření pak může obsahovat kód pro zpracování příchozích dat. Další možností by bylo použít NotificationCenter k předání dat do řadiče zobrazení nebo použít třídu Database pro zpracování dat.

vzor designu singletonu získal určitou kontroverzi, jednoduše proto, že je snadno zneužitelný. Při používání singletonů, mějte na paměti stav a závislosti. To, že je snadné mít globální přístup ke státu, neznamená, že je to dobrý nápad.

získejte najat jako vývojář iOS

Naučte se vytvářet aplikace pro iOS 14 pomocí Swift 5

přihlaste se do mého kurzu vývoje iOS a naučte se, jak začít svou kariéru jako profesionální vývojář iOS.

další čtení

a to je vše, co je k tomu! Seznámení s singletony je užitečným cílem, zvláště pokud vás zajímá architektura aplikací a design systémů.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.