írta Reinder de Vries január 10-én 2019 Az App Development, Swift

a szingulett egy olyan osztály, amelynek pontosan egy példánya létezik, amely globálisan elérhető. Hogyan lehet létrehozni egy singletont Swift – ben? És miért kellene vagy nem kellene?

ebben az oktatóanyagban belemerülünk a singletons-ba Swift-ben. Megtanulod, mi a singleton tervezési minta, és miért hasznos. Megbeszéljük a szingulettek létrehozásának szintaxisát Swift-ben. És a szinglik jó és rossz Használati esetei is szóba kerülnek.

Kész? Menjünk.

  1. Mi Az A Szingulett?
  2. Singleton Kódolása Swift-Ben
  3. Mikor Kell Használni A Singletonokat
  4. További Olvasat

Mi Az A Singleton?

a szingulett olyan osztály, amelyből csak egy példány létezik. Néhány példa:

  • egy vállalatnak csak egy CEO
  • egy API osztálynak csak egy soros kérési sora van
  • az operációs rendszernek csak egy fájlrendszere van
  • a naprendszer teste egy gravitációs pont körül forog
  • az I/O-t működtető alkalmazásnak csak egy alapértelmezett FileManager
  • a repülőgépnek csak egy pilótafülkéje van

a szingulett második tulajdonsága, hogy globális hozzáférési ponttal rendelkezik. Hozzáférhet egy szinguletthez, például. hívás funkciók rajta, bárhonnan az alkalmazás kódját.

tehát összefoglalva:

  1. a szingulett egy osztály, amelynek csak egy példánya van
  2. globálisan elérhető, azaz bárhol a kódjában

a gyakorlati iOS fejlesztés során gyakran használ szinguletteket. Tipikus osztályok, mint például NotificationCenter, UserDefaults, SKPaymentQueue a FileManager pedig shared vagy default tulajdonságokkal rendelkezik, amelyek szingulettek.

máskor érdemes lehet létrehozni egy singleton magad. Jó felhasználási eset egy API osztály, amely a singleton példányt a shared tulajdonságán keresztül tárja fel. A API.shared.makeAPICall() használatával egyetlen, egységes példányon keresztül érheti el az API-t. Ez lehetővé teszi például az API-hívások soros kezelését.

mielőtt megvitatnánk, hogy mikor használjuk a szinguletteket a legjobban (és mikor nem), derítsük ki, hogyan kell kódolni egy szingulettet Swift-ben.

jelentkezz iOS fejlesztőként

Tanuld meg, hogyan építhetsz iOS 14 alkalmazásokat a Swift 5 segítségével

regisztrálj az iOS fejlesztői tanfolyamomra, és tanuld meg, hogyan kezdheted el a karriered professzionális iOS fejlesztőként.

Singleton kódolása Swift-ben

ez a legjobb módszer egy singleton létrehozására Swift-ben:

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

és itt van, hogyan kell használni a singleton:

API.shared.doSomething()

létrehozunk egy API osztályt, amelynek egyetlen statikus tulajdonsága van, az úgynevezett shared. Ez a tulajdonság nem változtatható meg egyszer, mert állandó, és statikusan deklarálva van.

ez azt jelenti, hogy a sharedtulajdonságot a API osztályon keresztül érhetjük el. Ezt gyakran osztály tulajdonságnak nevezik. Hasonlítsa össze ezt egy normál példánytulajdonsággal, amely csak egy osztály példányán keresztül érhető el.

érdekes, hogy a shared tulajdonság inicializálja a API egy példányát a API osztályon belül. Egyfajta API objektumot hozunk létre, amely a API osztályon keresztül érhető el. De van még…

a init()osztály inicializáló private – vel van jelölve. Ez az private kulcsszó biztosítja, hogy az API osztály csak a API osztályon belül inicializálható.

más szavakkal, nem hozhat létre API példányt a API osztályon kívül! Ez biztosítja, hogy az általunk létrehozott API objektum legyen az egyetlen példány a kódunkban. Végül is nem lehet többet létrehozni belőle.

és most biztosítottuk, hogy az API osztály megfelel a szingulett két tulajdonságának:

  1. a shared statikus tulajdonságnak köszönhetően az API példány globálisan elérhető
  2. a private init() – nek köszönhetően az API osztály nem inicializálható a API osztályon kívül

mindez kissé absztraktnak tűnhet számodra, ezért bővítsük ki az előző példát néhány praktikusabb kóddal. Itt van:

a API osztály többnyire ugyanaz. Ez még mindig egy szingulett, és még mindig használja azokat a static let shared = API() és private init() bit kódokat.

itt van, mi változott:

  • a API osztálynak most van egy isRequestPending tulajdonsága. Itt kezdődik a veszély… nézze meg, hogyan biztosítja a isRequestPending logikai érték, hogy egyszerre csak egy API-kérés hajtható végre? (Ne feledje, hogy a isRequestPending egy példány tulajdonság.)
  • a API osztálynak makeAPIRequest() funkciója is van. Képzelje el, hogy ezt a funkciót felhasználhatjuk néhány adat visszaszerzésére egy webservice API-ból, például a Twitter-ből. a funkcióban láthatja, hogy egy kérés csak akkor tehető meg, ha jelenleg nincs más kérés függőben.
  • a API osztálynak van egy onReturnAPIRequest() funkciója is. Ez a funkció akkor kerül meghívásra, amikor az API kérés visszatér, azaz az online adatok letöltésre kerültek az alkalmazásba. A isRequestPending logikai érték ismét false értékre van állítva, és a kérelem adatai feldolgozásra kerülnek.

és itt van, hogyan tudjuk használni a API singleton bárhol a kódot:

API.shared.makeAPIRequest()

van még valami, amit meg kell beszélnünk. A API osztály most kezeli az úgynevezett állapotot. Az “állapotot” egy érzésnek tekintheti: vagy boldog vagy, vagy szomorú vagy, vagy dühös vagy stb. Válthat az egyik állapotból a másikba.

az API osztály két állapot között válthat:

  • olyan állapot, amelyben isRequestPending jelentése false
  • olyan állapot, amelyben isRequestPending true

ahogy a következő részben megtudhatja, az állam és a szinglik mindenféle pusztítást okozhatnak a kódjában. Kezelése állam rosszul az egyetlen legnagyobb oka singleton visszaélés.

mikor kell használni Singletons

mikor használja singletons? A The Gang of Four által az újrafelhasználható objektum-orientált szoftver elemei című könyv a következőket mondja. Használja a singleton mintát, amikor:

  • egy osztálynak pontosan egy példányának kell lennie, és az ügyfelek számára hozzáférhetőnek kell lennie egy jól ismert hozzáférési pontról
  • amikor az egyetlen példánynak bővíthetőnek kell lennie alosztályozással, és az ügyfeleknek képesnek kell lenniük egy kiterjesztett példány használatára a kód módosítása nélkül

ez összetett, de az, hogy:

  • akkor használj szingulettet, ha a kódodhoz egy osztálynak csak egy példánya szükséges (azaz a vállalat vezérigazgatója)
  • és ha bárhonnan elérhetőnek kell lennie a kódodban (pl., a fájlrendszer)

egy másik felhasználási eset az alosztály. A kódban lévő globális változókat nem lehet könnyen alosztályozni, ezért használ egy singleton osztályt. Továbbá, a szinguletteket egységesen lehet tesztelni függőségi injekció alkalmazásával. Az API példányt lecseréli egy APIMock példányra, és lehetővé teszi az API-hívások tesztelését a tényleges hálózati kérelmek benyújtása nélkül.

és mikor nem használsz szingliket? A kérdés megválaszolásához vissza kell térnünk a korábban tárgyalt állami elvhez.

A kezdő iOS Fejlesztők számára gyakori buktató az állapot és annak függőségeinek rossz kezelése. Képzelje el, hogy olyan alkalmazást épít, amely a API osztályt használja, amellyel korábban dolgoztunk.

minden alkalommal, amikor kibővíti az API osztályt, egyre több tulajdonságra tapad, például:

  • a userID tulajdonság, amely nyomon követi a bejelentkezett felhasználót, miután a login() API-hívás megtörtént
  • a tweets tulajdonság Twitter-adatokkal, miután az getTweets() hívás megtörtént
  • a spinner tulajdonság UIActivityIndicatorView – vel, amelyet hozzáad egy nézetvezérlőhöz, amikor egy kérés elindult

eleinte ennek sok értelme van. Végül is a API osztály bárhol elérhető a kódban. Tehát a Tweet nézet vezérlőben használhatja a API.shared.tweets tömböt, a Beállítások vezérlőben pedig a userID segítségével gyorsan megmondhatja az API-nak, hogy kinek a beállításait kell megváltoztatni.

sajnos, az állam most az egész hely. A API osztálynak vannak olyan függőségei, amelyek nem kapcsolódnak az API osztály egyetlen felelősségéhez. A kódod egy tál spagetti lett, összekuszálva. Lehet, hogy a kód jól működik, de lehetetlen fenntartani és kiterjeszteni.

nézzünk egy példát. A korábban definiált onReturnAPIRequest() függvény a szoros összekapcsolódás szélén áll…

itt van, amit mérlegelünk:

  • a onReturnAPIRequest() meghívásra kerül, amikor egy API webservice kérés visszatér, azaz amikor az adatok az alkalmazásba kerülnek. Ezeknek az adatoknak valahova el kell menniük – például egy Tweet Nézetvezérlőnek. Hogyan továbbítja az adatokat a API – ről a nézetvezérlőre?
  • nyilvánvaló választás, ha csak hivatkozást hozunk létre a viewController – re a API osztályban. Amikor az adatok bejönnek, kódolhat valamit, például viewController.tweets = tweetsData. Ez sajnos gyenge architektúra, mert most a API és a nézetvezérlő szorosan össze van kapcsolva. Lehetetlen (vagy nehéz) egységtesztet végezni, és valószínűleg problémákat okoz bármelyik osztály kiterjesztésekor.
  • jobb olyan mechanizmust választani, amely nem szorosan összekapcsolja mindkét osztályt. Az egyik lehetőség az lenne, hogy adja át a lezárás onReturnAPIRequest(), amely végrehajtásra kerül, amikor a kérés visszatér. Ez a Bezárás ezután tartalmazhat kódot a bejövő adatok kezelésére. Egy másik lehetőség a NotificationCenter használata az adatok továbbítására a nézetvezérlőnek, vagy egy Database osztály használata az adatok kezelésére.

a singleton tervezési minta némi vitát váltott ki, egyszerűen azért, mert könnyű visszaélni. Amikor szinguletteket használ, ügyeljen az állapotra és a függőségekre. Csak azért, mert könnyű globális hozzáférést biztosítani az államhoz, ez nem jelenti azt, hogy jó ötlet.

jelentkezz iOS fejlesztőként

Tanuld meg, hogyan építhetsz iOS 14 alkalmazásokat a Swift 5 segítségével

regisztrálj az iOS fejlesztői tanfolyamomra, és tanuld meg, hogyan kezdheted el a karriered professzionális iOS fejlesztőként.

további olvasmányok

és ennyi az egész! A singletons megismerése érdemes cél, különösen, ha érdekel az alkalmazás architektúrája és a rendszerek tervezése.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.