File di costanti globali in Swift


336

Nei miei progetti Objective-C utilizzo spesso un file delle costanti globali per memorizzare elementi come nomi e chiavi di notifica NSUserDefaults. Sembra qualcosa del genere:

@interface GlobalConstants : NSObject

extern NSString *someNotification;

@end

@implementation GlobalConstants

NSString *someNotification = @"aaaaNotification";

@end

Come faccio esattamente la stessa cosa in Swift?


3
Puoi vedere questo tutorial
Anish Parajuli

Risposte:


765

Struttura come spazio dei nomi

L'IMO il modo migliore per affrontare quel tipo di costanti è creare un Struct.

struct Constants {
    static let someNotification = "TEST"
}

Quindi, ad esempio, chiamalo così nel tuo codice:

print(Constants.someNotification)

Nidificazione

Se desideri un'organizzazione migliore, ti consiglio di utilizzare sottostrutture segmentate

struct K {
    struct NotificationKey {
        static let Welcome = "kWelcomeNotif"
    }

    struct Path {
        static let Documents = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
        static let Tmp = NSTemporaryDirectory()
    }
}

Quindi puoi semplicemente usare per esempio K.Path.Tmp

Esempio del mondo reale

Questa è solo una soluzione tecnica, l'implementazione effettiva nel mio codice è più simile a:

struct GraphicColors {

    static let grayDark = UIColor(0.2)
    static let grayUltraDark = UIColor(0.1)

    static let brown  = UIColor(rgb: 126, 99, 89)
    // etc.
}

e


enum Env: String {
    case debug
    case testFlight
    case appStore
}

struct App {
    struct Folders {
        static let documents: NSString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
        static let temporary: NSString = NSTemporaryDirectory() as NSString
    }
    static let version: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
    static let build: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String

    // This is private because the use of 'appConfiguration' is preferred.
    private static let isTestFlight = Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt"

    // This can be used to add debug statements.
    static var isDebug: Bool {
        #if DEBUG
        return true
        #else
        return false
        #endif
    }

    static var env: Env {
        if isDebug {
            return .debug
        } else if isTestFlight {
            return .testFlight
        } else {
            return .appStore
        }
    }
}

123
Personalmente, ho cercato un Constant.swiftfile con strutture separate ma non incapsulato in una grande Constantsstruttura per evitare una chiamata troppo lunga a una costante. Quindi chiamo NotificationKey.WelcomeinveceConstants.NotificationKey.Welcome
Kevin Hirsch il

2
@KevinHirsch non è una cattiva idea. D'altra parte: se ho il prefisso .Constants, so che non è una cosa locale, ma un po 'nello spazio dei nomi Costanti
brainray

3
@brainray Vedo il tuo punto ma nel mio codice le costanti non sono mai locali (sempre in a Constants.swift) e hanno sempre lo stesso aspetto: a partire da maiuscole e con un nome di categoria significativo come "NotificationKey", "SegueIdentifier" o "Path", .. Così posso vedere facilmente quando è una costante;)
Kevin Hirsch,

15
Questo non è compatibile con il codice Objective-C (le strutture, né le costanti di livello superiore vengono esportate per Objective-C).
RndmTsk,

3
@VarunNahariastruct Helpers { static func RGBCOLOR(red: Int, green: Int, blue: Int) -> UIColor { return UIColor(red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: 1) } static func IOS7VERSION() -> Bool { return UIDevice.currentDevice().systemVersion.compare("7.0", options: .NumericSearch, range: nil, locale: nil) != .OrderedAscending } }
André Slotta,

109

Sono in ritardo alla festa.

Non importa come gestisco il file constants in modo che abbia più senso per gli sviluppatori mentre scrivo il codice rapidamente.

PER URL:

//URLConstants.swift

  struct APPURL {

    private struct Domains {
        static let Dev = "http://test-dev.cloudapp.net"
        static let UAT = "http://test-UAT.com"
        static let Local = "192.145.1.1"
        static let QA = "testAddress.qa.com"
    }

    private  struct Routes {
        static let Api = "/api/mobile"
    }

    private  static let Domain = Domains.Dev
    private  static let Route = Routes.Api
    private  static let BaseURL = Domain + Route

    static var FacebookLogin: String {
        return BaseURL  + "/auth/facebook"
    }
}

Per i CLIENTI:

//FontsConstants.swift
struct FontNames {

    static let LatoName = "Lato"
    struct Lato {
        static let LatoBold = "Lato-Bold"
        static let LatoMedium = "Lato-Medium"
        static let LatoRegular = "Lato-Regular"
        static let LatoExtraBold = "Lato-ExtraBold"
    }
}

PER TUTTI I TASTI UTILIZZATI IN APP

//KeyConstants.swift
    struct Key {

        static let DeviceType = "iOS"
        struct Beacon{
            static let ONEXUUID = "xxxx-xxxx-xxxx-xxxx"
        }

        struct UserDefaults {
            static let k_App_Running_FirstTime = "userRunningAppFirstTime"
        }

        struct Headers {
            static let Authorization = "Authorization"
            static let ContentType = "Content-Type"
        }
        struct Google{
            static let placesKey = "some key here"//for photos
            static let serverKey = "some key here"
        }

        struct ErrorMessage{
            static let listNotFound = "ERROR_LIST_NOT_FOUND"
            static let validationError = "ERROR_VALIDATION"
        }
    }

PER COSTANTI A COLORI:

//ColorConstants.swift
struct AppColor {

    private struct Alphas {
        static let Opaque = CGFloat(1)
        static let SemiOpaque = CGFloat(0.8)
        static let SemiTransparent = CGFloat(0.5)
        static let Transparent = CGFloat(0.3)
    }

    static let appPrimaryColor =  UIColor.white.withAlphaComponent(Alphas.SemiOpaque)
    static let appSecondaryColor =  UIColor.blue.withAlphaComponent(Alphas.Opaque)

    struct TextColors {
        static let Error = AppColor.appSecondaryColor
        static let Success = UIColor(red: 0.1303, green: 0.9915, blue: 0.0233, alpha: Alphas.Opaque) 
    }

    struct TabBarColors{
        static let Selected = UIColor.white
        static let NotSelected = UIColor.black
    }

    struct OverlayColor {
        static let SemiTransparentBlack = UIColor.black.withAlphaComponent(Alphas.Transparent)
        static let SemiOpaque = UIColor.black.withAlphaComponent(Alphas.SemiOpaque)
        static let demoOverlay = UIColor.black.withAlphaComponent(0.6)
    }
}

Puoi racchiudere tutti questi file in un gruppo comune chiamato Costanti nel tuo progetto Xcode.

E per di più guarda questo video


grazie, ho trovato il tuo metodo più conveniente (almeno per me), ben fatto! 8)
Yatko

2
meglio della mia risposta
Kirit Vaghela il

1
Non dimenticare di importare UIKit :)
alicanbatur,

2
Le variabili statiche non aumentano le dimensioni dell'app durante il runtime poiché tutte le variabili statiche vengono caricate quando l'app inizia a funzionare?
Anand,

1
So che ha più di un anno, ma volevo solo dire che è fantastico. Ben fatto per condividere le conoscenze su questo 👌🏻
user1898712

28

Anche se preferisco il modo di @ Francescu (usando una struttura con proprietà statiche), puoi anche definire costanti e variabili globali:

let someNotification = "TEST"

Si noti tuttavia che diversamente dalle variabili / costanti locali e dalle proprietà class / struct, i globuli sono implicitamente pigri, il che significa che vengono inizializzati quando si accede per la prima volta.

Lettura consigliata: variabili globali e locali e anche le variabili globali in Swift non sono variabili


Questo è il modo corretto di dichiarare le costanti. L'approccio struct è ottimo per la leggibilità.
João Nunes,

1
Non consiglio questo approccio in quanto annulla il principio OOP ..
Anish Parajuli

1
@ThatlazyiOSGuy 웃 Swift è un linguaggio OOP ma l'attenzione è rivolta anche alla programmazione funzionale (almeno concetti più funzionali). Questo è un modo perfettamente valido per dichiarare le costanti sebbene offuscherà gravemente lo spazio dei nomi String per qualsiasi IDE.
Dean Kelly,

Dici che la differenza sta nella pigrizia implicita, ma se usi una var statica calcolata, agirà nello stesso modo di un globale e invierà una e una sola volta una volta chiamata.
Dean Kelly,

1
aspetta, ma il potenziale problema è che struct è un tipo di valore, la classe è un tipo di riferimento, l'assegnazione di un'istanza di classe in struct comporterà la classe nel tipo di valore, che è indesiderato ??
Martian2049,

23

Constant.swift

import Foundation

let kBaseURL = NSURL(string: "http://www.example.com/")

ViewController.swift

var manager = AFHTTPRequestOperationManager(baseURL: kBaseURL)

Per quale motivo usa kBaseURL invece di BASEURL? Grazie!
Josep Escobar,

Problaly sta anche sviluppando applicazioni Android ed è Android standard.
BoranA

5
C'è un modello per le costanti in Objective-C, le dichiarerai sempre usando il formato seguente: k + nome del caso del cammello della proprietà
Laur Stefan

20

Considera le enumerazioni. Questi possono essere logicamente suddivisi per casi d'uso separati.

enum UserDefaultsKeys: String {
    case SomeNotification = "aaaaNotification"
    case DeviceToken = "deviceToken"
}

enum PhotoMetaKeys: String {
    case Orientation = "orientation_hv"
    case Size = "size"
    case DateTaken = "date_taken"
}

Un vantaggio unico si verifica quando si verifica una situazione di opzioni reciprocamente esclusive, come:

for (key, value) in photoConfigurationFile {
    guard let key = PhotoMetaKeys(rawvalue: key) else {
        continue // invalid key, ignore it
    }
    switch (key) {
    case.Orientation: {
        photo.orientation = value
    }
    case.Size: {
        photo.size = value
    }
    }
}

In questo esempio, riceverai un errore di compilazione perché non hai gestito il caso di PhotoMetaKeys.DateTaken.


1
Il caso Enum non può contenere valori duplicati. Quindi questo non si adatta a tutti gli scenari.
Aaina Jain,

@AainaJain In realtà, se per i valori vengono utilizzate proprietà calcolate invece del valore grezzo enum, è facile avere diversi casi enum che generano lo stesso valore.
future-adam,

14

O semplicemente in GlobalConstants.swift:

import Foundation

let someNotification = "aaaaNotification"

8

Come altri hanno già detto, tutto ciò che viene dichiarato al di fuori di una classe è globale.

Puoi anche creare singleton:

class TestClass {
    static let sharedInstance = TestClass()
    // Anything else goes here
    var number = 0
}

Ogni volta che vuoi usare qualcosa di questa classe, ad esempio scrivi:

TestClass.sharedInstance.number = 1

Se ora scrivi println(TestClass.sharedInstance.number)da qualsiasi parte del progetto, verrai stampato 1nel registro. Funziona con tutti i tipi di oggetti.

tl; dr: ogni volta che vuoi rendere tutto globale in una classe, aggiungi static let sharedInstance = YourClassName()alla classe e indirizza tutti i valori della classe con il prefissoYourClassName.sharedInstance


una domanda per te. altre risposte implicano l'uso di struct per archiviare informazioni, ma il potenziale problema è che struct è un tipo di valore, la classe è un tipo di riferimento, l'assegnazione dell'istanza di classe in struct comporterà la classe nel tipo di valore, che è indesiderato, giusto?
Martian2049,

5

Cosa ho fatto nel mio progetto Swift
1: creare un nuovo file Swift
2: creare una const e una costante statica in esso.
3: per l'utilizzo basta usare YourStructName.baseURL

Nota: dopo aver creato l'inizializzazione richiede poco tempo, quindi verrà visualizzato in altri controller della vista dopo 2-5 secondi.

import Foundation

    struct YourStructName {
    static let MerchantID = "XXX"
    static let MerchantUsername = "XXXXX"
    static let ImageBaseURL = "XXXXXXX"
    static let baseURL = "XXXXXXX"
    }

3

Per le notifiche puoi usare l'estensione, in questo modo:

extension Notification.Name {
    static let testNotification = "kTestNotification"
}

E usalo come NotificationCenter.default.post(name: .testNotification, object: nil)


2

Per avere costanti globali nelle mie app, questo è quello che faccio in un file Swift separato :

import Foundation

struct Config {
    static let baseURL = "https://api.com"

    static APIKeys {
        static let token = "token"
        static let user = "user"
    }

    struct Notifications {
        static let awareUser = "aware_user"
    }
}

È facile da usare e chiamare ovunque così:

print(Config.Notifications.awareUser)

1

Colori

extension UIColor {
    static var greenLaPalma: UIColor {
        return UIColor(red:0.28, green:0.56, blue:0.22, alpha:1.00)
    }
}

Caratteri

enum CustomFontType: String {
    case avenirNextRegular = "AvenirNext-Regular",
    avenirDemiBold = "AvenirNext-DemiBold"
}

extension UIFont {
    static func getFont(with type: CustomFontType, size: CGFloat) -> UIFont {
        let font = UIFont(name: type.rawValue, size: size)!

        return font
    }
}

Per altro - tutto uguale a come nella risposta accettata.


1

Secondo i rapidi documenti, le variabili globali sono dichiarate nell'ambito dei file.

Le variabili globali sono variabili definite al di fuori di qualsiasi contesto di funzione, metodo, chiusura o tipo

Basta creare un file rapido (ad esempio: Constnats.swift) e dichiarare lì le tue costanti:

// Constants.swift

let SOME_NOTIF = "aaaaNotification"

e chiamalo da qualsiasi parte del tuo progetto senza la necessità di menzionare il nome di struttura, enum o classe.

// MyViewController.swift

NotificationCenter.default.post(name: SOME_NOTIF, object: nil)

Penso che questo sia molto meglio per la leggibilità del codice.


1

Versione Swift 4

Se si desidera creare un nome per NotificationCenter:

extension Notification.Name {
    static let updateDataList1 = Notification.Name("updateDataList1")
}

Iscriviti alle notifiche:

NotificationCenter.default.addObserver(self, selector: #selector(youFunction), name: .updateDataList1, object: nil)

Invia notifica:

NotificationCenter.default.post(name: .updateDataList1, object: nil)

Se vuoi solo una classe con variabili da usare:

class Keys {
    static let key1 = "YOU_KEY"
    static let key2 = "YOU_KEY"
}

O:

struct Keys {
    static let key1 = "YOU_KEY"
    static let key2 = "YOU_KEY"
}

1

Si possono usare anche enumerazioni senza case.

Vantaggio: non possono essere istanziati.

enum API {
    enum Endpoint {
        static let url1 = "url1"
        static let url2 = "url2"
    }
    enum BaseURL {
        static let dev = "dev"
        static let prod = "prod"
    }
}

0

Impara da Apple è il modo migliore.

Ad esempio, la notifica da tastiera di Apple:

extension UIResponder {

    public class let keyboardWillShowNotification: NSNotification.Name

    public class let keyboardDidShowNotification: NSNotification.Name

    public class let keyboardWillHideNotification: NSNotification.Name

    public class let keyboardDidHideNotification: NSNotification.Name

}

Ora imparo da Apple:

extension User {
    /// user did login notification
    static let userDidLogInNotification = Notification.Name(rawValue: "User.userDidLogInNotification")
}

Cosa c'è di più, NSAttributedString.Key.foregroundColor:

extension NSAttributedString {

    public struct Key : Hashable, Equatable, RawRepresentable {

        public init(_ rawValue: String)

        public init(rawValue: String)
    }
}

extension NSAttributedString.Key {

    /************************ Attributes ************************/

    @available(iOS 6.0, *)
    public static let foregroundColor: NSAttributedString.Key // UIColor, default blackColor

}

Ora imparo da Apple:

extension UIFont {

    struct Name {

    }

}

extension UIFont.Name {

    static let SFProText_Heavy = "SFProText-Heavy"
    static let SFProText_LightItalic = "SFProText-LightItalic"
    static let SFProText_HeavyItalic = "SFProText-HeavyItalic"

}

utilizzo:

let font = UIFont.init(name: UIFont.Name.SFProText_Heavy, size: 20)

Imparare da Apple è il modo in cui tutti possono fare e promuovere facilmente la qualità del codice.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.