BLACK FRIDAY: Save 50% on all my Swift books and bundles! >>

Enumerații

Enumerații – de obicei le numim "enum"-uri – îți oferă posibilitatea de a-ți defini propriile tale tipuri valori în Swift. În unele limbaje de programare sunt lucruri simple, dar Swift le adaugă o cantiate incredibilă de putere dacă vrei mai mult decât lucrurile de bază.

Să începem cu un exemplu simplu de mai devreme:

func getHaterStatus(weather: String) -> String? {
    if weather == "sunny" {
        return nil
    } else {
        return "Hate"
    }
}

Această funcție acceptă un string care definește tipul vremii de acum. Problema este că, un string nu este o decizie bună pentru acel tip de date – este "rain", "rainy" sau "raining"? Sau poate "showering", "drizzly" sau "stormy"? Mai rău, ce se întâmplă dacă o persoană scrie "Rain" cu R mare și altcineva scrie "Ran" pentru că nu se uita atunci când scria?

Enum-urile rezolvă această problemă lăsându-te să definești un nou tip, care definește variabilele posibile pe care le poate ține. De exemplu, am putea spune că există cinci tipuri de vreme: soare, nori, ploaie, vânt și zăpadă. Dacă le scriem într-un enum, înseamnă că Swift va accepta doar acele cinci valori – orice altceva va declanșa o eroare. Iar de obicei în spate enum-urile sunt doar numere, care sunt mult mai rapide atunci când lucrezi cu ele decât string-urile.

Să punem asta în cod:

enum WeatherType {
    case sun, cloud, rain, wind, snow
}

func getHaterStatus(weather: WeatherType) -> String? {
    if weather == WeatherType.sun {
        return nil
    } else {
        return "Hate"
    }
}

getHaterStatus(weather: WeatherType.cloud)

Uită-te la primele trei linii: linia 1 dă un nume tipului nostru, WeatherType. Asta vei folosi în loc de String sau Int în codul tău. Linia 2 definește cele cinci cazuri posibile pe care le poate avea enum-ul, așa cum am subliniat mai devreme. Convențional ele încep cu litere mici, deci "sun", "cloud" ș.a. Iar linia 3 este doar o acoladă închisă, care incheie enum-ul.

Acum hai să ne uităm cum este folosit: Am modificat getHaterStatus() altfel încât să accepte o valoare de tip WeatherType. Declarația condiționată est de asemenea rescrisă să fie comparată cu WeatherType.sun, care este valoarea noastră. Amintește-ți, această verificare este doar un număr în spate, ceea ce este foarte rapid.

Acum, mai citește codul odată, pentru că sunt pe cale să-l rescriu făcând două modificări importante. Ești pregătit?

enum WeatherType {
    case sun
    case cloud
    case rain
    case wind
    case snow
}

func getHaterStatus(weather: WeatherType) -> String? {
    if weather == .sun {
        return nil
    } else {
        return "Hate"
    }
}

getHaterStatus(weather: .cloud)

Am făcut două modificări. Prima, fiecare tip de vreme se află acum pe propria linie. Poate pare o schimbare minoră, și într-adevăr în acest exemplu este, dar va deveni importantp curând. Cea de-a doua modificare este că am scris if weather == .sun – nu trebuia să scriu tipul în mod specific WeatherType.sun deoarece Swift știe că eu compar cu o variabilă de tipul WeatherType, deci folosește deducere de tip.

Enum-urile sunt folositoare în special în blocurile switch/case, deoarece Swift cunoaște deja toate valorile pe care enum-ul le poate avea pentru a se asigura că toate sunt acoperite. De exemplu, am putea încerca să rescriem funcția getHaterStatus() în felul acesta:

func getHaterStatus(weather: WeatherType) -> String? {
    switch weather {
    case .sun:
        return nil
    case .cloud, .wind:
        return "dislike"
    case .rain:
        return "hate"
    }
}

Da, îmi dau seama că "haters gonna dislike" nu este o lirică extraordinară, dar este în orice caz academic deoarece codul nu va buildui: nu ia în considerare cazul .snow, și Swift dorește ca toate cazurile să fie acoperite. Trebuie să adaugi un caz pentru el sau să adaugi cazul default.

Enum-uri cu valori adiționale

Unul dintre cele mai puternice proprietăți Swift este că enumerațiile pot avea valori atașate pe care tu le definești. Pentru a extinde exemplul nostru dubios, voi adăuga o valoare cazului .wind astfel încât să putem specifica cât de tare bate vântul. Modifică codul astfel:

enum WeatherType {
    case sun
    case cloud
    case rain
    case wind(speed: Int)
    case snow
}

După cum poți vedea, celelalte valori nu necesită o valoare viteză – am pus-o doar la wind. Acum logia adevărată: Swift ne lasă să adăugăm condiții extra blocului switch/case astfel încât un caz se va potrivi doar dacă acele condiții sunt îndeplinite. Aceasta folosește cuvântul cheie let pentru a accesa o valoare din interiorul cazului, apoi cuvântul cheie where pentru potrivirea modelului.

Aici noua funcție:

func getHaterStatus(weather: WeatherType) -> String? {
    switch weather {
    case .sun:
        return nil
    case .wind(let speed) where speed < 10:
        return "meh"
    case .cloud, .wind:
        return "dislike"
    case .rain, .snow:
        return "hate"
    }
}

getHaterStatus(weather: WeatherType.wind(speed: 5))

Poți vedea că .wind apare de două ori, dar prima oară este adevărat pentru că vântul bate mai încet de 10 kilometrii pe oră. Dacă vântul bate cu 10 sau mai mult, nu se va potrivi. Cheia este să folosești let pentru a obține valoarea din interiorul enum-ului (pentru a declara un nume de constantă pe care îl poți referenția) apoi folosește condiția where pentru a verifica.

Swift evaluează switch/case de la cap la coadă, și se oprește de îndată ce găsește o potrivire. Asta înseamnă că dacă case .cloud, .wind: apare înainte de case .wind(let speed) where speed < 10: atunci acela va fi executat – și rezultatul final se schimbă.

Deci, gândește-te atent cum ordonezi cazurile!

Sfat: În Swift opționalele sunt implementate folosind enum-uri cu valori asociate. Există doup cazuri: none, și some, cu some având orice valoare care se află în interiorul opționalului.

Save 50% in my WWDC sale.

SAVE 50% All our books and bundles are half price for Black Friday, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

BUY OUR BOOKS
Buy Pro Swift Buy Pro SwiftUI Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.