Skrevet av Reinder De Vries januar 10 2019 I App Utvikling, Swift

en singleton er en klasse som nøyaktig en forekomst eksisterer, som kan nås globalt. Hvordan du oppretter en singleton I Swift? Hvorfor skulle eller burde ikke du?

i denne opplæringen vil vi dykke inn i enkeltfødte I Swift. Du lærer hva singleton design mønster er, og hvorfor det er nyttig. Vi vil diskutere syntaksen for å lage enkeltfødte I Swift. Og vi kommer inn i gode og dårlige brukssaker for enkeltfødte.

Klar? Kom igjen.

  1. Hva Er En Singleton?
  2. Koding Av En Singleton I Swift
  3. Når Skal Du Bruke Enkeltfødte
  4. Videre Lesing

Hva Er En Singleton?

en singleton er en klasse hvor bare en forekomst eksisterer. Noen eksempler:

  • et selskap har bare en CEO
  • EN API-klasse har bare en seriell forespørselskø
  • et operativsystem har bare ett filsystem
  • et solsystemlegeme dreier seg om ett gravitasjonspunkt
  • en app som gjør I/O har bare en standard FileManager
  • et fly har bare ett flydekk

den andre egenskapen til en singleton er at den har et globalt tilgangspunkt. Du kan få tilgang til en singleton, f.eks. ring funksjoner på den, fra hvor som helst i appens kode.

så, for å oppsummere:

  1. en singleton er en klasse som bare har en forekomst
  2. den kan nås globalt, dvs. hvor som helst i koden din

i praktisk iOS-utvikling bruker du ofte enkeltfødte. Typiske klasser som NotificationCenter, UserDefaults, SKPaymentQueue og FileManager har shared eller default egenskaper som er enkeltfødte.

andre ganger kan du ønske å lage en singleton selv. En god brukstilfelle er en API – klasse som avslører singleton-forekomsten via sin shared – egenskap. Du bruker API.shared.makeAPICall() for å få TILGANG TIL API gjennom en enkelt, enhetlig forekomst. Dette lar deg for eksempel administrere API-kall serielt.

Før vi diskuterer når enkeltfødte er best brukt (og når ikke), la oss finne ut hvordan du koder en singleton I Swift.

Bli ansatt som iOS-utvikler

Lær å bygge iOS 14-apper med Swift 5

Registrer deg for mitt iOS-utviklingskurs, og lær hvordan du starter din karriere som profesjonell iOS-utvikler.

Koding En Singleton I Swift

Dette er den beste måten å lage en singleton I Swift:

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

Og her er hvordan du bruker singleton:

API.shared.doSomething()

vi lager en API – klasse som har en statisk egenskap kalt shared. Denne egenskapen kan ikke endres når den er satt, fordi den er konstant, og den er deklarert statisk.

det betyr at vi kan få tilgang til shared – egenskapen via klassen API. Dette kalles ofte en klasse eiendom. Sammenlign dette med en vanlig instansegenskap, som bare kan nås via en forekomst av en klasse.

det som er interessant er at egenskapen shared initialiserer en forekomst av API i API – klassen. Vi lager liksom et API objekt som kan nås gjennom klassen API. Men det er mer…

klasseinitialisatoren init() er merket med private. Dette nøkkelordet private sikrer at klassen API bare kan initialiseres i klassen API.

med andre ord kan du ikke opprette en forekomst av API utenfor klassen API! Dette sikrer at API – objektet vi har opprettet, er den eneste forekomsten i koden vår. Tross alt kan du ikke lage mer av det.

og nå har vi sørget for at API – klassen overholder de to egenskapene til en singleton:

  1. takket være den statiske egenskapen shared kan API – forekomsten nås globalt
  2. takket være private init() kan API – klassen ikke initialiseres utenfor API – klassen

alt dette kan høres litt abstrakt ut for deg, så la oss utvide det forrige eksemplet med litt mer praktisk kode. Her er hva:

API klassen er for det meste den samme. Det er fortsatt en singleton, og den bruker fortsatt de static let shared = API() og private init() biter av kode.

Her er hva som er endret:

  • klassen API har nå en isRequestPending egenskap. Det er her faren begynner… Se hvordan isRequestPending boolsk sikrer at bare EN API-forespørsel kan gjøres om gangen? (Merk at isRequestPending er en instansegenskap.)
  • klassen API har også en makeAPIRequest() – funksjon. Tenk deg at vi kan bruke denne funksjonen til å få noen data tilbake fra en webservice API, som Twitter. i funksjonen kan du se at en forespørsel kun kan gjøres når ingen annen forespørsel er for tiden ventende.
  • klassen API har også en onReturnAPIRequest() – funksjon. Denne funksjonen påberopes når API-forespørselen returnerer, dvs. online data er lastet ned i appen. Boolsk isRequestPending er satt til false igjen, og forespørselsdataene behandles.

Og her er hvordan vi kan bruke API singleton hvor som helst i koden vår:

API.shared.makeAPIRequest()

Det er noe annet vi må diskutere. Klassen API styrer nå noe som kalles stat. Du kan se «stat» som en følelse: du er enten glad eller du er trist, eller du er sint, og så videre. Du kan bytte fra en stat til den andre.

klassen API kan bytte mellom to tilstander:

  • en tilstand der isRequestPending er false
  • en tilstand der isRequestPending er true

som du vil lære i neste avsnitt, stat og enkeltfødte kan skape alle slags kaos på koden din. Administrerende staten dårlig er den største enkeltårsaken til singleton misbruk.

Når Skal Du Bruke Enkeltfødte

når bruker du enkeltfødte? Boken Design Patterns: Elements Of Gjenbrukbare Objektorientert Programvare Av Gjengen På Fire har følgende å si. Bruk singleton-mønsteret når:

  • det må være nøyaktig en forekomst av en klasse, og den må være tilgjengelig for klienter fra et kjent tilgangspunkt
  • når den eneste forekomsten skal være utvidbar ved subclassing, og klienter skal kunne bruke en utvidet forekomst uten å endre koden

det er komplekst, men hva det koker ned til er:

  • Bruk en singleton når koden din ikke krever mer enn en forekomst av en klasse (DVS. KONSERNSJEF i selskapet)
  • og når den må være tilgjengelig fra hvor som helst i koden din (dvs., filsystemet)

Et annet brukstilfelle er subclassing. En global variabel i koden din kan ikke lett underklasse, så det er derfor du bruker en singleton-klasse. I tillegg kan enkeltfødte være enhet testet ved hjelp av avhengighet injeksjon. Du erstatter API – forekomsten med en APIMock – forekomst, og får muligheten til å teste API-kall uten å gjøre de faktiske nettverksforespørslene.

Og når bruker du ikke enkeltfødte? For å svare på det spørsmålet, må vi gå tilbake til statsprinsippet vi diskuterte tidligere.

en vanlig fallgruve for nybegynnere iOS-utviklere er å administrere staten og dens avhengigheter dårlig. Tenk deg at du bygger en app som bruker klassen API vi jobbet med tidligere.

Hver gang DU utvider API-klassen, tack du på flere og flere egenskaper, for eksempel:

  • en userID egenskap som holder styr på den innloggede brukeren, når API-anropet login()
  • en tweets egenskap med Twitter-data, når getTweets() – anropet er gjort
  • en spinner egenskap med en UIActivityIndicatorView som du legger til i en visningskontroller når en forespørsel har startet

i begynnelsen Gir dette mye mening å gjøre. Tross alt kan API – klassen nås hvor som helst i koden din. Så I Tweet View Controller kan du bruke API.shared.tweets – arrayet, og i Innstillingskontrolleren kan du bruke userID for raskt å fortelle API-innstillingene hvis innstillinger skal endres.

Dessverre er staten din nå over alt. Klassen API har avhengigheter til en rekke klasser som ikke er relatert til API-klassens enkeltansvar. Koden din har blitt en bolle med spaghetti, alle sammenflettet. Koden kan fungere OK, men det er umulig å vedlikeholde og utvide.

La oss se på et eksempel. Funksjonen onReturnAPIRequest() vi definerte tidligere, er på randen av å bli tett koblet…

Her er det vi vurderer:

  • onReturnAPIRequest() kalles når EN API webservice forespørsel returnerer, dvs. når data kommer inn i appen. Disse dataene må gå et sted – En Tweet View Controller for eksempel. Hvordan sender du dataene fra API til visningskontrolleren?
  • et åpenbart valg er å bare lage en referanse til viewController i API – klassen. Når dataene kommer inn, kan du kode noe som viewController.tweets = tweetsData. Dette er dårlig arkitektur, dessverre, for nå er API og visningskontrolleren tett koblet. Det er umulig (eller vanskelig) å enhetstest, og sannsynligvis skape problemer når man utvider en klasse.
  • Det er bedre å velge en mekanisme som ikke tett par begge klassene. Ett alternativ ville være å sende en nedleggelse til onReturnAPIRequest(), som utføres når forespørselen returnerer. Denne lukkingen kan da inneholde kode for å håndtere innkommende data. Et annet alternativ ville være å bruke NotificationCenter for å sende dataene til visningskontrolleren, eller å bruke en Database – klasse for å håndtere dataene.

singleton design mønster har fått noen kontrovers, rett og slett fordi det er lett å misbruke. Når du bruker enkeltfødte, vær oppmerksom på tilstand og avhengigheter. Bare fordi det er lett å ha global tilgang til staten, betyr det ikke at det er en god ide.

Bli ansatt som iOS-utvikler

Lær å bygge iOS 14-apper med Swift 5

Registrer deg for mitt iOS-utviklingskurs, og lær hvordan du starter din karriere som profesjonell iOS-utvikler.

Videre Lesing

Og det er alt som skal til! Bli kjent med enkeltfødte er et verdifullt mål, spesielt hvis du er interessert i apparkitektur og systemdesign.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.