Arquivo de constantes globais no Swift


336

Nos meus projetos Objective-C, geralmente uso um arquivo de constantes globais para armazenar itens como chaves e nomes de notificação NSUserDefaults. Parece algo como isto:

@interface GlobalConstants : NSObject

extern NSString *someNotification;

@end

@implementation GlobalConstants

NSString *someNotification = @"aaaaNotification";

@end

Como faço exatamente a mesma coisa no Swift?


3
Você pode ver isso tutoiral
— Anish Parajuli 웃

Respostas:


764

Estruturas como espaço para nome

Na IMO, a melhor maneira de lidar com esse tipo de constantes é criar um Struct.

struct Constants {
    static let someNotification = "TEST"
}

Então, por exemplo, chame assim no seu código:

print(Constants.someNotification)

Aninhamento

Se você deseja uma organização melhor, aconselho o uso de subestruturas segmentadas

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

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

Então você pode apenas usar, por exemplo K.Path.Tmp

Exemplo do mundo real

Esta é apenas uma solução técnica, a implementação real no meu código se parece mais com:

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
Pessoalmente, procurei um Constant.swiftarquivo com estruturas separadas, mas não encapsulado em uma grande Constantsestrutura para evitar chamadas muito longas para uma constante. Então eu chamo em NotificationKey.Welcomevez deConstants.NotificationKey.Welcome
— Kevin Hirsch

2
@KevinHirsch não é uma má idéia. Por outro lado: se eu tiver o prefixo .Constants, eu sei que não é uma coisa local, mas tipo de no Constantes namespace
— brainray

3
@brainray Entendo o seu ponto, mas no meu código, as constantes nunca são locais (sempre em a Constants.swift) e sempre parecem iguais: começando com maiúsculas e com um nome de categoria significativo como "NotificationKey", "SegueIdentifier" ou "Path", .. . Assim eu posso ver facilmente quando é uma constante;)
— Kevin Hirsch

15
Isso não é compatível com o código Objective-C (estruturas, nem constantes de nível superior são exportadas para 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

Estou atrasado para a festa.

Não importa como eu gerencio o arquivo de constantes, para que faça mais sentido para os desenvolvedores enquanto escrevia o código rapidamente.

PARA 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"
    }
}

Para CLIENTES:

//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"
    }
}

PARA TODAS AS CHAVES USADAS NO 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"
        }
    }

PARA CONSTANTES DE CORES:

//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)
    }
}

Você pode agrupar todos esses arquivos em um grupo comum chamado Constants no seu projeto Xcode.

E para mais, assista a este vídeo


obrigado, achei seu método o mais conveniente (pelo menos para mim), muito bem! 8)
— Yatko 8/17

2
melhor do que a minha resposta
— Kirit Vaghela

11
Não se esqueça de importar o UIKit :)
— alicanbatur 28/03

2
As variáveis ​​estáticas não aumentam o tamanho do aplicativo durante o tempo de execução, pois todas as variáveis ​​estáticas são carregadas quando o aplicativo começa a ser executado?
— Anand

11
Eu sei que isso tem mais de um ano, mas só queria dizer que isso é fantástico. Bem feito para compartilhar o conhecimento sobre este 👌🏻
— user1898712

28

Embora eu prefira a maneira do @ Francescu (usando uma estrutura com propriedades estáticas), você também pode definir constantes e variáveis ​​globais:

let someNotification = "TEST"

Observe, porém, que diferentemente das variáveis ​​/ constantes locais e das propriedades de classe / estrutura, os globais são implicitamente preguiçosos, o que significa que são inicializados quando são acessados ​​pela primeira vez.

Leitura sugerida: Variáveis ​​globais e locais , e também variáveis ​​globais no Swift não são variáveis


Esta é a maneira correta de declarar as constantes. A abordagem struct é muito boa para facilitar a leitura.
— João Nunes

11
Eu não recomendo esta abordagem, uma vez que anula OOP principle..You pode ver isso tutoiral
— Anish Parajuli 웃

11
@ThatlazyiOSGuy 웃 Swift é uma linguagem OOP, mas o foco também está na programação funcional (pelo menos, mais conceitos funcionais). Essa é uma maneira perfeitamente válida de declarar constantes, embora ofusque severamente o espaço de nomes String para qualquer IDE.
— Dean Kelly

Você diz que a diferença está na preguiça implícita, mas se você usar uma var estática calculada, ela atuará da mesma maneira que um global e despachará uma e apenas uma vez chamada.
— Dean Kelly

11
aguarde, mas o problema potencial é que struct é do tipo valor, classe é tipo de referência, a atribuição de instância da classe no struct tornará a classe grosseira no tipo de valor, o que é indesejável?
— precisa saber é o seguinte

23

Constant.swift

import Foundation

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

ViewController.swift

var manager = AFHTTPRequestOperationManager(baseURL: kBaseURL)

Por que motivo usa o kBaseURL em vez do BASEURL? Obrigado!
— Josep Escobar

Provavelmente, ele também está desenvolvendo aplicativos para Android e é um padrão para Android.
— Borana

5
Há um padrão para constantes em Objective-C, você sempre vai declará-los usando o seguinte formato: k + camelo nome caso da propriedade
— Laur Stefan

20

Considere enumerações. Eles podem ser divididos logicamente para casos de uso separados.

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

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

Um benefício exclusivo ocorre quando você tem uma situação de opções mutuamente exclusivas, como:

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
    }
    }
}

Neste exemplo, você receberá um erro de compilação porque não lidou com o caso de PhotoMetaKeys.DateTaken.


11
O caso enum não pode conter valores duplicados. Portanto, isso não se encaixa em todos os cenários.
— Aaina Jain

@AainaJain Na verdade, se as propriedades computadas forem usadas para os valores em vez do valor bruto da enumeração, é fácil ter casos diferentes da enumeração que produzam o mesmo valor.
— future-adam

14

Ou apenas no GlobalConstants.swift:

import Foundation

let someNotification = "aaaaNotification"

8

Como outros já mencionaram, qualquer coisa declarada fora de uma classe é global.

Você também pode criar singletons:

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

Sempre que você quiser usar algo desta classe, por exemplo, escreva:

TestClass.sharedInstance.number = 1

Se você agora escreve println(TestClass.sharedInstance.number)de qualquer lugar do seu projeto, imprime 1no log. Isso funciona para todos os tipos de objetos.

tl; dr: sempre que você quiser tornar tudo em uma classe global, adicionar static let sharedInstance = YourClassName()à classe e endereçar todos os valores da classe com o prefixoYourClassName.sharedInstance


uma pergunta para voce. outras respostas envolvem o uso de struct para armazenar informações, mas o problema em potencial é que struct é um tipo de valor, classe é um tipo de referência; atribuir uma instância de classe em struct irá classificar a classe como tipo de valor, o que é indesejável, certo?
— precisa saber é o seguinte

5

O que fiz no meu projeto Swift
1: Criar um novo arquivo Swift
2: Crie uma estrutura e uma constante estática nele.
3: Para usar, use YourStructName.baseURL

Nota: Após a criação da inicialização, leva pouco tempo para que seja exibida em outros controladores de exibição após 2-5 segundos.

import Foundation

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

3

Para notificações, você pode usar a extensão, algo como isto:

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

E use-o como NotificationCenter.default.post(name: .testNotification, object: nil)


2

Para ter constantes globais em meus aplicativos, é isso que faço em um arquivo Swift separado :

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"
    }
}

É fácil de usar e ligar para qualquer lugar como este:

print(Config.Notifications.awareUser)

1

Cores

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

Fontes

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
    }
}

Para outros - tudo o mesmo que na resposta aceita.


1

De acordo com os documentos rápidos, as variáveis ​​globais são declaradas no escopo do arquivo.

Variáveis ​​globais são variáveis ​​definidas fora de qualquer contexto de função, método, fechamento ou tipo

Basta criar um arquivo rápido (por exemplo: Constnats.swift) e declarar suas constantes lá:

// Constants.swift

let SOME_NOTIF = "aaaaNotification"

e chame-o de qualquer lugar do seu projeto, sem a necessidade de mencionar struct, enum ou nome da classe.

// MyViewController.swift

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

Eu acho que isso é muito melhor para a legibilidade do código.


1

Versão Swift 4

Se você deseja criar um nome para o NotificationCenter:

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

Assine as notificações:

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

Enviar notificação:

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

Se você quer apenas uma classe com variáveis ​​para usar:

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

Ou:

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

1

Enums sem caixa também podem ser usados.

Vantagem - Eles não podem ser instanciados.

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

0

Aprenda com a Apple é a melhor maneira.

Por exemplo, a notificação do teclado da 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

}

Agora eu aprendo com a Apple:

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

Além do mais 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

}

Agora eu aprendo 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"

}

uso:

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

Aprenda com a Apple é a maneira que todos podem fazer e promover facilmente a qualidade do seu código.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.